how to avoid objcopy blowing up the file? - elf

I use objcopy to extract/replace some section is an ELF file on a windows system.
>objcopy.exe -V
GNU objcopy 2.17.50 20060824
Copyright 2005 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License. This program has absolutely no warranty.
This works in general.
But my elf file contains debug information which I need to remove before delivery to decrese the filesize.
I found tht option -g or --strip-debug should do what I want:
>"objcopy.exe" --strip-debug -I elf32-big -O elf32-big with-debug.elf without-debug.elf
But it fails miserably. instead of making the file smaller it blows up the file size from ~20MB to 3GB before failing with:
objcopy.exe: without-debug.elf: File truncated
objcopy.exe: without-debug.elf: No space left on device
how do I corectly remove debug information from ELF using objcopy?
Don't know if this is important but objcopy issues some warnings for most ot the sections in the ELF like this:
BFD: without-debug.elf: warning: allocated section `.sdata' not in segment

Sounds like a bug in binutils.
You are using 10 year old version, and not an official release but a snapshot taken at random time.
I would try current release of binutils (version 2.28) first -- there is a chance whatever bug you are hitting has already been fixed. And if it hasn't, you can report it in binutils bugzilla.

Related

How does Gem5 accept and decode executables from user?

Eg:
/home/gem5/build/X86/gem5.opt --debug-flags=TLB,Cache
/home/gem5/configs/example/se.py --cpu-type=DerivO3CPU --caches
--mem-type=SimpleMemory -I 10000 -c out --options="1 in_16.txt out.txt" >> test2.txt
The bold part in the SE CLI for Gem5 shows my input to it. How exactly does Gem5 process this and obtain the instructions to be simulated? Which files should I be looking into for this? As far as I know, no tutorials mention this.
out is a regular ELF userland executable, e.g. a C hello world, just like the ones you would run on your Linux host.
Usage of dynamically linked executable is described at: How to run a dynamically linked executable syscall emulation mode se.py in gem5? so generally statically linking is easier.
gem5 parses the ELF format, places memory into the right locations, puts the PC in the right location, and kicks off simulation, just like the exec syscall of the Linux kernel would.
Several runnable examples are available here.

How to run a dynamically linked executable syscall emulation mode se.py in gem5?

After How to solve "FATAL: kernel too old" when running gem5 in syscall emulation SE mode? I managed to run a statically linked hello world under certain conditions.
But if I try to run an ARM dynamically linked one against the stdlib with:
./out/common/gem5/build/ARM/gem5.opt ./gem5/gem5/configs/example/se.py -c ./a.out
it fails with:
fatal: Unable to open dynamic executable's interpreter.
How to make it find the interpreter? Hopefully without copying my cross' toolchain's interpreter on my host's root.
For x86_64 it works if I use my native compiler, and as expected strace says that it is using the native interpreter, but it does not work if I use a cross compiler.
The current FAQ says it is not possible to use dynamic executables: http://gem5.org/Frequently_Asked_Questions but I don't trust it, and then these presentations mention it:
http://www.gem5.org/wiki/images/0/0c/2015_ws_08_dynamic-linker.pdf
http://research.cs.wisc.edu/multifacet/papers/learning_gem5_tutorial.pdf
but not how to actually use it.
QEMU user mode has the -L option for that.
Tested in gem5 49f96e7b77925837aa5bc84d4c3453ab5f07408e
https://www.mail-archive.com/gem5-users#gem5.org/msg15582.html
Support for dynamic linking has been added in November 2019
At: https://gem5-review.googlesource.com/c/public/gem5/+/23066
It was working for sure at that point, but then it broke at some point and needs fixing.....
arm 32-bit https://gem5.atlassian.net/browse/GEM5-461
arm 64-bit https://gem5.atlassian.net/browse/GEM5-828
If you have a root filesystem to use, for example one generated by Buildroot you can do:
./build/ARM/gem5.opt configs/example/se.py \
--redirects /lib=/path/to/build/target/lib \
--redirects /lib64=/path/to/build/target/lib64 \
--redirects /usr/lib=/path/to/build/target/usr/lib \
--redirects /usr/lib64=/path/to/build/target/usr/lib64 \
--interp-dir /path/to/build/target \
--cmd /path/to/build/target/bin/hello
Or if you are using an Ubuntu cross compiler toolchain for example in Ubuntu 18.04:
sudo apt install gcc-aarch64-linux-gnu
aarch64-linux-gnu-gcc -o hello.out hello.c
./build/ARM/gem5.opt configs/example/se.py \
--interp-dir /usr/aarch64-linux-gnu \
--redirects /lib=/usr/aarch64-linux-gnu/lib \
--cmd hello.out
You have to add any paths that might contain dynamic libraries as a separate --redirect as well. Those are enough for C executables.
--interp-dir sets the root directory where the dynamic loader will be searched for, based on ELF metadata which says the path of the loader. For example, buildroot ELF files set that path to /lib/ld-linux-aarch64.so.1, and the loader is a file present at /path/to/build/target/lib/ld-linux-aarch64.so.1. As mentioned by Brandon, this path can be found with:
readelf -a $bin_name | grep interp
The main difficulty with syscall emulation dynamic linking, is that we want somehow:
linker file accesses to go to a magic directory to find libraries there
other file accesses from the main application to go to normal paths, e.g. to read an input file in the current working directory
and it is hard to detect if we are in the loader or not, especially because this can happen via dlopen in the middle of a program.
The --redirects option is a simple solution for that.
For example /lib=/path/to/build/target/lib makes it so that if the guest would access the C standard library /lib/libc.so.6, then gem5 sees that this is inside /lib and redirects the path to /path/to/build/target/lib/libc.so.6 instead.
The slight downside is that it becomes impossible to actually access files in the /lib directory of the host, but this is not common, so it works in most cases.
If you miss any --redirect, the dynamic linker will likely complain that the library was not found with a message of type:
hello.out: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
If that happens, you have to find the libstdc++.so.6 library in the target filesystem / toolchain and add the missing --redirect.
It later broke at https://gem5.atlassian.net/browse/GEM5-430 but was fixed again.
Downsides of dynamic linking
Once I got dynamic linking to work, I noticed that it actually has the following downsides, which might or not be considerable depending on the application:
the dynamic linker has to run some instructions, and if you have a very minimal userland test executable, and are running on a low CPU like O3, then this startup can dominate runtime, so watch out for that
ExecAll does not show symbol names for stdlib functions, you just get offsets from some random nearest symbol e.g. #__end__+274873692728. Maybe something along these lines would work: Debugging shared libraries with gdbserver but not sure
dynamically jumping to a stdlib function for the first time requires going through the dynamic linking machinery, which can create problems if you are trying to control a microbench.
I actually already hit this once: the dynamic version of a program was doing something extra that and that compounded with a gem5 bug broke my experiment, and cost me a few hours of debugging.
Interpreters like Python and Java
Python and Java are just executables, and the script to execute an argument to the executable.
So in theory, you can run them in syscall emulation mode e.g. with:
build/ARM/gem5.opt configs/example/se.py --cmd /usr/bin/python --options='hello.py arg1 arg2'
In practice however hugely complex executable like interpreters are likely to have syscalls that not yet implemented given the current state of gem5 as of November 2019, see also: When to use full system FS vs syscall emulation SE with userland programs in gem5?
Generally it is not hard to implement / ignore uneeded calls though, so give it a shot. Related threads:
Java: Running Java programs in gem5(or any language which is not C)
Python: 3.6.8 aarch64 fails with "fatal: syscall unused#278 (#278) unimplemented.", test setup
Old answer
I have been told that as of 49f96e7b77925837aa5bc84d4c3453ab5f07408e (May 2018) there is no convenient / well tested way for running dynamically linked cross arch executables in syscall emulation: https://www.mail-archive.com/gem5-users#gem5.org/msg15585.html
I suspect however that it wouldn't be very hard to patch gem5 to support it. QEMU user mode already supports that, you just have to point to the root filesystem with -L.
The cross-compiled binary should have an .interp entry if it's a dynamic executable.
Verify it with readelf:
readelf -a $bin_name | grep interp
The simulator is setup to find this section in main executable when it loads the executable into the simulated address space. If this sections exists, a c-string is set to point to that text (normally something like /lib64/ld-linux-x86-64.so.2). The simulator then calls glibc's open function with that c-string as the parameter. Effectively, this opens the dynamic linker-loader for the simulator as a normal file. The simulator then maps the file into the simulated address space in phases with mmap and mmap_fixed.
For cross compilation, this code must fail. The error message follows it directly if the simulator cannot open the file. To make this work, you need to debug the opening process and possibly the subsequent pasting of the loader into the address space. There is mechanism to set the program's entry point into the loader rather than directly into the code section of the main binary. (It's done through the auxiliary vector on the stack.) You may need to play around with that as well.
The interesting code is (as of 05/29/19) in src/base/loader/elf_object.cc.
I encountered this problem after I just cross compiled the code. You can try to add "--static" after the command.

Downloading JUST g++ binary

This question may seem stupid to you guys, but I am in a situation where I have no access to command line, and I need a version of g++ on my computer so I can compile my c++ code.
I looked on the GNU repository, and I have NO idea how to build and also install the environment.
Where can I simply just download the 'g++' file, without going through all these trouble?
Thanks in advance
Where can I simply just download the 'g++' file, without going through all these trouble?
Downloading the g++ file will not do you any good: the GNU C++ compiler distribution consists of several hundreds of files. The g++ is just the compiler front end, you'll also need cc1plus (the actual compiler), header files and libraries.

Reason for objdump dependence on toolchain

Why are there separate objdump binaries for different toolchains, something like arm-none-eabi-objdump?
Why can't the objdump executable be used alongwith the particular switch? For example -marm to get the dump about the arm binary?
The binary files for different architectures are interpreted in a different way. So the same binary code will interpret into totally different machine instructions on different CPU architectures. As for objdump, the most clear example can be shown with --disassemble switch, which is instructing it to convert the binary into assembly instructions. But the assembly instructions are totally different for different architectures, so the objdump utility has to know the right one.

Program "g++ not found in path" in Eclipse Juno CDT in Ubuntu

Eclipse June CDT reports g++ not found in path, how to fix this?
Typically, g++ will be installed when gcc (GNU Compiler Collection) is installed.
First confirm that you have g++ installed.
You can check this by typing the following in a terminal: which g++.
The response ought to be /usr/bin/g++.
If you find g++ installed, in eclipse go to project->properties->C/C++ Build->Discovery Options, under tools GCC C++ Compiler, put the exact path to g++ instead of g++ (if g++ alone does not work).
You will find this link useful:
What is the difference between g++ and gcc?
If you still have problems, do get back with feedback.
I had similar problem and it is solved by
Installing g++ The GNU C++ complier using ubuntu software centre and
Changing in -
Window -> Preferences -> C/C++ -> Build -> Settings -> Discovery -> CDT GCC Build in Complier Settings [Shared]
From: ${COMMAND} -E -P -v -dD "${INPUTS}"
To: /usr/bin/${COMMAND} -E -P -v -dD "${INPUTS}"
I hope it helps. I think if you add it to the project as mentioned in the first answer, you will need to add all the time for new projects. And if you add as I wrote you don't need to add it for new projects.
I have exactly the same problem. I never had problems with eclipse before under linux and now it wont even compile code. I tried to change the name of the g++ and gcc compilers to their exact location in project->properties->c/c++ Build->discovery options etc. nothing helped, I tried to reinstall eclipse and did an initialize, added the path to the variables etc.. Nothing worked so fare. The project I am working on is quiet big and I rather would like eclipse to manage the source and makefile, instead of doing it manually
Linux Mint 15 Eclispe: Version: 3.8.1 (I tried it with the latest version as well ... nothing changed)
g++ --version g++ (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3 Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
gcc --version gcc (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3 Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
example:
#include // not resolved using namespace std;
int main() {
std::cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
return 0;
}
Well the code above is not what bothers me, as I can fix it by adding the includes of the exact c++ include path, but the code just wont compile. Wired enough eclipse gives me the error:
Description Resource Path Location Type Program "g++" not found in PATH Preferences, C++/Build/Settings/Discovery, [CDT GCC Builtin Compiler Settings] options C/C++ Scanner Discovery Problem
but it appears to me to be possible to compile single files, by opening them and pressing crt+b, but the whole project wont compile.
Fixed the problem this morning:
- got the latest eclipse
- created a new workspace
- created a new project
after a few seconds the very same error disappears
This issue was fixed for me once I deleted eclipse's .metedata folder, called eclipse -initialize from the command line and started eclipse again. HTH
Creating a new Workspace directory on Eclipse startup solved the problem for me.