Disable relocations when linking with LLD - llvm

Is there an option for lld that will tell it not to perform relocations. I don't want PIC code, I just want relocations not to be performed. (Yes I know this will result in an executable that doesn't work.)

Turns out to be an easy and fairly obvious solution - just pass -r or --relocatable. Then it won't apply relocations but will store them in the output file instead.
Edit: Unfortunately this does not quite have the effect I want, because you can't use --gc-sections and --relocatable at the same time.

Related

What is section ".debug_info" in an elf file?

I have an elf file, while analysing the mapfile and elf using elfparser, I saw a section called .Debug_info, which is taking largest memory.
I am compiling for xtensa DSP, using xt-xc++, I haven't used -g option also given -o2 optimization level.
is it possible to remove this for release builds?
section called .debug_info, which is taking largest memory.
Note that this section does not have SHF_ALLOC flag, and therefore does not take any RAM at runtime (it only takes space in the filesystem). Of course if you use ramdisk, then that section still does cost you RAM in the end.
is it possible to remove this for release builds?
Yes: none of the .debug* sections are necessary at runtime, and all of them can be safely stripped.
-g0 and -s option didn't work.
It's likely that you are getting .debug_* sections from libraries that you are linking in, and not from your own code. The -g was present when the libraries were compiled, so building with -g0 doesn't have any effect.
It's surprising that -s didn't work, but maybe your compiler interprets this flag differently.
In any case, you should use strip --strip-debug to get rid of .debug_* sections (note: this does not remove the symbol table).
The best practice is actually to compile all your code with full debug info (-g), save the full debug binary for post-mortem analysis, use strip --strip-debug to make a release binary, and use that binary for actual distribution.
If/when the release binary crashes and leaves a core dump, having (saved) full-debug exactly matching binary greatly improves post-mortem analysis you can do.

Loading GNU ld script with dlopen

I have an C++14 code that should load an arbitrary shared object file with dlopen. Unfortunately on some systems (e.g. my archlinux, reportedly also applies to some .so on ubuntu and gentoo), these so-files can be "GNU ld scripts" instead of the actual binaries.
For reference, here is the content of my /usr/lib/libm.so:
/* GNU ld script
*/
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/libm.so.6 AS_NEEDED ( /usr/lib/libmvec.so.1 ) )
I have found a couple of code-pieces that deal with this issue in ghc or ruby. I would like to avoid resorting to manually parsing the text file based parsing the dlerror text and the file. I feel that is terribly evil and I won't be able to implement and maintain corner cases of this format.
Is there a clean way to implement handling this case? Frankly I am puzzled as to why dlopen does not actually handle these tranparaently.
Note: Considering the aforementioned patches I think this is not simply an issue with my system configuration / versions. If this should work out-of-the-box with dlopen (bug instead of missing feature), please let me know.
The linker scripts are intended to be used by the linker, not the run-time linker.
The GNU ld script comment should have been a giveaway: this is for ld, not for ld.so. ;-)
See for instance: http://www.math.utah.edu/docs/info/ld_3.html
So I guess using this with dlopen() would mean mimicking/importing part of ld's magic for this, which would confirm your fears about resorting to manually parsing the text and maintaining terribly evil code.
EDIT: There seems to be one thing that can help you though:
https://www.sourceware.org/ml/libc-alpha/2011-07/msg00152.html
<gnu/lib-names.h> should contain a define LIBM_SO which should point you to the correct file that you can actually dlopen().
That means that normally no evil code would be necessary.

Reference function of shared library in executable with relocations but without PIC

I am wondering myself if it is possible to build & link a executable using a shared object so that it is not using PIC (therefore PLT) but load-time relocations.
I think if this is possible, the code section has to be re writeable (which should principal be no problem).
If I try with no additional gcc parameters, it uses PIC (usually, to create a PIC shared lib, I have to add -fPIC).
I know that it is possible with data, for that case a R_386_COPY relocation is executed.
So, is this possible for functions? And if, with which gcc parameters?
is this possible for functions?
Sure.
And if, with which gcc parameters?
No version of ld that I know of will do that (as generally this is considered the wrong thing to do). You'll have to build ld from source, and apply a patch to make it do what you want.
the code section has to be re writeable
Correct.
(which should principal be no problem).
Many environments, such as e.g. SELinux prohibit writeable and executable mappings, as such mappings are exceedingly insecure.
So while your binary with writable code section would run in some environments with no problem, it will not run in many others.

call stack for code compiled without -g option (gcc compiler)

How do I analyze the core dump (using gdb)
which is not compiled with -g GCC option ?
Generate a map file. The map file will tell you the address that each function starts at (as an offset from the start of the exe so you will need to know the base address its loaded too). So you then look at the instruction pointer and look up where it falls in the map file. This gives you a good idea of the location in a given function.
Manually unwinding a stack is a bit of a black art, however, as you have no idea what optimisations the compiler has performed. When you know, roughly, where you are in the code you can generally work out what ought to be on the stack and scan through memory to find the return pointer. its quite involved however. You effectively spend a lot of time reading memory data and looking for numbers that look like memory addresses and then checking that to see if its logical. Its perfectly doable and I, and I'm sure many others, have done it lots of times :)
With ELF binaries it is possible to separate the debug symbols into a separate file. Quoting from objcopy man pages:
Link the executable as normal (using the -g flag). Assuming that is is called foo then...
Run objcopy --only-keep-debug foo foo.dbg to create a file containing the debugging info.
Run objcopy --strip-debug foo to create a stripped executable.
Run objcopy --add-gnu-debuglink=foo.dbg foo to add a link to the debugging info into the stripped executable.
that should not be a problem , you can compile the source again with -g option and pass gdb the core and the new compiled debug binary, it should work without any problem.
BTW You can generate a map file with the below command in gcc
gcc -Wl,-Map=system.map file.c
The above line should generate the map file system.map, Once the map file is generated you can map the address as mentioned above but i am not sure how are you going to map the share library, this is very difficult

Determining what object files have caused .dll size increase [C++]

I'm working on a large c++ built library that has grown by a significant amount recently. Due to it's size, it is not obvious what has caused this size increase.
Do you have any suggestions of tools (msvc or gcc) that could help determine where the growth has come from.
edit
Things i've tried: Dumpbin the final dll, the obj files, creating a map file and ripping through it.
edit again
So objdump along with a python script seems to have done what I want.
If gcc, objdump. If visual studio, dumpbin.
I'd suggest doing a diff of the output of the tool for the old (small) library, vs. the new (large) library.
keysersoze's answer (compare the output of objdump or dumpbin) is correct. Another approach is to tell the linker to produce a map file, and compare the map files for the old and new versions of the DLL.
MSVC: link.exe /MAP
GCC and binutils: ld -M (or gcc -Wl,-M)
On Linux it should be quite easy to see if new files have been added with a recursive diff. They would certainly create an increase in the library size. You can then go an use the size command line tool on Linux to get the sizes of each of the new object files and sum them up. Then compare that sum to your library increase and check how much it differs.
G'day,
If you have any previous versions of the object file laying around can you run the size command to see which segment has grown?
Couple of questions:
Are you on a *nix platform or a Windows platform?
Which compiler are you using?
Was the compiler recently changed?
Was the -g flag added recently? (obvious question 1)
Was the object previously stripped? (obvious question 2)
Was the object dynamically linked previously? (obvious question 3)
Edit: If the code is under SCM, can you check out a version of the source that gave you the smaller object. Then compare:
the size of the source trees by doing a du -sk on the old source tree and then the new source tree without having built anything.
the number of files by doing something like find ./tree_top ( -name *.h -o -name *.cpp ) | wc -l
the location of an increased number of files by doing a find ./tree_top ( -name *.h -o -name *.cpp ) -print | sort > treelist and then do the same for the new larger tree. Doing a simple sdiff will show any large number of new files.
the size of code base, even a simple count of trailing semi-colons will give you a good basic mechanism for comparison between the two.
the Makefiles or build env. for the project to see if different options or settings have crept in to the build itself.
HTH
BTW Please post your findings here as I'm sure many people are interested in what you find out.
cheers,