How to count the uses of undefined symbols in an object file? - eclipse

Suppose I'm "forensically" examining an object file that somebody else compiled. I don't have the source, and can't rely on debug symbols either. Still, I can use:
objdump -C -t my_object.o \
| sed -r '/\\*UND\\*/!d; s/000+\s+\*UND\*\s+000+ //;' \
| sort
to get the external symbols it uses.
But what if what I'm after is the count of uses of each of these symbols? Is there a way to get that without, say, arduously parsing the disassembled code?
Notes:
A GNU system (e.g. Linux)
Assume basic tools used in C++ software development are installed.

For functions you could look at the number of relocations, for example:
// test.cc:
void foo();
int main() {
foo();
foo();
}
$ c++ -c test.cc
$ objdump -r test.o | grep foo
0000000000000005 R_X86_64_PC32 _Z3foov-0x0000000000000004
000000000000000a R_X86_64_PC32 _Z3foov-0x0000000000000004
Here we have two relocations, each corresponding to one function call.

Related

Why is this docopt string not working either with or without optional args?

Here is the complete docopt string I used:
foo.
Usage:
foo [options] <file> -o <output>
foo --help | --version
Options:
-h, --help print this help message.
--target <target> target.
--version print the version.
According to the official parser, either foo a -o b or foo --target abc a -o b is not correctly parsed. What could be possible reasons for this case? Any help would be appreciated.
I'm not entirely sure about the allowed combinations of options for your script, but here's something that should be close.
Just for fun, I wrote a script that has similar options to yours to test this out with the latest docopts.
I found it simplest to write just [options] in the main Usage section, and have all the options below as alternatives, with no specific combinations required.
I'm on macOS so I'm using bash 3.2 (with patched docopts.sh to fix some Mac issues). You can avoid some of the code in this script if you're on bash 4.x - see the commented-out section with --auto option and docopt_print_ARGS function. Currently you would need bash 4.x to avoid patching docopts.sh.
#!/bin/bash
#
# foo.
#
# Usage:
# foo [options] <file>
# foo --help | --version
#
# Options:
# -t, --target <target> target.
# -o, --output <output> output.
# -h, --help print this help message.
# --version print the version.
#
# bash 3.2 (patched docopts.sh) - include set -x to see the args easily
source docopts.sh
usage=$(docopt_get_help_string "$0")
set -x
eval "$(docopts -G ARGS -V "$VERSION" -h "$usage" : "$#")"
# On bash 4.x, replace preceding section with this, or use -A instead of -G above
# source docopts.sh --auto "$#"
# docopt_print_ARGS
This parses the Usage section OK and processes command lines such as:
foo --target a -o b file1
foo --target a --output b file1
foo --target a file1
Partial output with set -x to show args processed correctly:
$ ./foo --target a file1 --output b
...
++ ARGS_target=a
++ ARGS_output=b
++ ARGS_file=file1
++ ARGS_help=false
++ ARGS_version=false
Thanks for #RichVel's efforts. Yesterday I finally found out the underlying (stupid) cause for this problem.
In the official online parser the first part, i.e. foo shouldn't be used. --target abc a -o b works fine in the online example.
Regarding my question, the bug actually comes from that docopt.rs stores --target abc in flag_target instead of arg_target.

gcc command line structure arguments

I try to compile a c file with gcc version 6.3.0 20170516 (Raspbian 6.3.0-18+rpi1+deb9u1).
I run the compiler in the source file's folder, but I keep getting the 'file not found' error message for the last argument ('bcm2835').
gcc -o gpio -l rt /home/pi/bcm2835-1.15/src/bcm2835.c -l bcm2835
/usr/bin/ld: cannot find -lbcm2835
collect2: error: ld returned 1 exit status
AFAIK, The gcc does not specify the third argument, I have no idea what this 3rd argument is used for and where to find it.
If I omit that argument, I get several error lines, each for one of the internal commands, like:
undefined reference to bcm2835_init
I also wish to know what the rt stands for. I could not find it in the official gcc docs.
Thanks
After -l, there should be no space. So it should be -lrt (not -l rt) and it should be -lbcm2835 (not -l bcm2835).
You need to add a linker search path with -L (uppercase L) right before calling -lbcm2835.
The input file should usually be last (that's the argument ending with main.c). That would be
gcc -o main -lrt -lbcm2835 /home/pi/bcm2835-1.15/main.c
-l links a library to the program. -L sets the library search path such that -l will find the libraries specified.
See this page for details on -l and -L.

LFS: GCC links wrong

I'm stuck on chapter 6.20 of the current LFS book. I get:
$ readelf -l a.out | grep Requesting
[Requesting program interpreter: /tools/lib64/ld-linux-x86-64.so.2]
instead of the desired:
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
The other tests lower down in the chapter all succeed.
This is my second time through the whole book being extremely careful and I got the same result last time around. Could there be some mistake?
For guidance it just said "The most likely reason is that something went wrong with the specs file adjustment.". That's a reference to 6.10 where it says "It is a good idea to visually inspect the specs file to verify the intended change was actually made" but there's no guidance as to what these intended changes are. But on this second go round I did check in /tools/lib/gcc/x86_64-pc-linux-gnu/7.2.0/specs that there was no mention of "tools" and the /usr paths were mentioned.
I seem to have solved it by making another specs file for the new compiler:
gcc -dumpspecs | sed -e 's#/tools##g' > `dirname $(gcc --print-libgcc-file-name)`/specs
After that, I redo the test:
echo 'int main(){}' > dummy.c
cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'
And all is well.

How can I make sure that the GNU linker ld is page aligning sections without a linker script?

As the title suggests, I'm trying to compile and subsequently link a binary, and I want the sections (text, data, bss, etc.) to be paged-aligned. To achieve that, I'm trying to pass the --no-omagicoption to ld. The literal command I'm using (in my Makefile) is:
ld --no-omagic -o build/initlink.out $^
ld --help says the option should have the following effect:
--no-omagic Page align data, make text readonly
But if I do an nm -n on the output, the first symbol in each section is not aligned. For example:
$ nm -n build/initlink.out | grep ' [tT] ' | head -n 1
00000000004000f0 T main
$ nm -n build/initlink.out | grep ' [dD] ' | head -n 1
00000000006d74b0 d vsscanf.basefix
$ nm -n build/initlink.out | grep ' [bB] ' | head -n 1
00000000006e7200 B __bss_start
If it's important, one thing with which I'm trying to link is a static library (.a extension).
Is there anything that I could be doing wrong? Is there another way to ensure page alignment of sections, without resorting to a linker script? I've tried using the --section-alignment option, but when I do, I'm told that it's unrecognized. The static library defines some strange symbols (involving "linker sets," which I've found to be woefully undocumented) with which I was running into issues, so I want to try to do this without having to do anything but tell the linker to put sections in certain places.

run a prolog code with swipl in a command line

I am searching for swipl the similar feature as perl -e
In particular, I want to run prolog code in this fashion:
swipl --wanted-flag "fact(a). message:-writeln('hello')." -g "message" -t halt
This is possible to do with
swipl -f file -g "message" -t halt
where the prolog clauses are written in file
I am running swipl on the server side that takes user input as prolog clauses, therefore writing a file on the server is not a good idea.
One thing you can do is to use load_files/2 with the option stream, and load from standard input, not from an argument (you can still pass the entry point as an argument, I guess):
Say in a file fromstdin.pl you have:
main :-
load_files(stdin, [stream(user_input)]),
current_prolog_flag(argv, [Goal|_]),
call(Goal),
halt.
main :- halt(1).
and with this you can do:
$ echo 'message :- format("hello~n").' | swipl -q -t main fromstdin.pl -- message
|: hello
The comments by #false to this answer and the question will tell you what this |: is, if you are wondering, but if it annoys you, just do:
$ echo 'message :- format("hello~n").' \
| swipl -q -t main fromstdin.pl -- message \
| cat
hello
instead.
This will let you read any Prolog from standard input and call an arbitrary predicate from it. Whether this is a clever thing to do, I don't know. I would also not be surprised if there is a much easier way to achieve the same.