I'm trying to get ELF data (Section Header Table, SHT) for Linux system utilities.
I've noticed that I can get this info for my own programs when those were compiled such that objects (.o) file is created. I also managed to get SHT for bash via readelf, by typing:
readelf -l /bin/bash
However, it doesn't work for some utilities, like gunzip. For instance, I want to type-in something like:
readelf -S tar -czvf large_file.tar.gz large_file.dat
and get a set of execution attributes, like the ones in the below picture:
Anyone knows how to achieve this?
Thanks in advance,
Alexander.
The manpage for readelf shows that it expects to receive the path to an ELF binary file as its argument, not an entire command like tar -czvf large_file.tar.gz large_file.dat.
To find ELF data for tar, do this:
which tar
readelf -S <path to tar binary>
On my system, the path to tar is simply /bin/tar.
Related
As I understand it, the purpose of the Source: header in an rpm spec file is to specify a file (often a tar archive) that is used as the package payload. This source file is typically generated beforehand, perhaps by make, and then rpmbuild is executed afterwards.
I'm wondering if it's possible to cut make out of the picture and just use rpmbuild. Can the source file be created as part of the rpmbuild process itself, perhaps in the %build or %install step in the spec file?
If so, what does one use as the Source: header? I can't just leave it blank, because rpmbuild complains. Is there a way to tell rpm that the payload file is generated from within the spec file, and not supplied externally?
I don't want to create the source file separately because that would mean keeping track of the package name and version number in two places: in the rpm spec file, and also in whatever makefile or other script creates the payload file. It seems like I should be able to do everything from within the spec file.
You want to call
%setup -q -c -T
see [1]. Example:
Name: test
Version: 1
Release: 1%{?dist}
Summary: Test
License: ...
%description
Test
%prep
%setup -q -c -T
%build
echo "int main() { return 0; } " > test.cpp
gcc -o test test.cpp
%install
install -Dpm 0755 test %{buildroot}%{_bindir}/test
%files
%{_bindir}/test
%changelog
...
[1] http://www.rpm.org/max-rpm/s1-rpm-specref-macros.html
I had the a similar problem recently. I ended up writing a script that read the spec file and did all the work. We no longer had to manage Makefiles and spec files and whatever other ways some of our developers were managing this.
The script is publicly posted on github at:
https://github.com/alexnelsone/jenkins-rpm-build/blob/master/README.md.
It parses the info out of the spec file and then does all the work for you.
I'd like to copy an executable ELF file via:
$ objcopy -O binary myfile.elf myfile.bin
Unfortunately:
$ chmod +x myfile.bin
$ ./myfile.bin
results in: cannot execute binary file
Is there any way to retain the files executability?
To be executable by the execve(2) syscall, a file usually has to be some elf(5) file (or some script, or some old a.out format). But see also binfmt_misc
Your objcopy(1) command is loosing the essential meta-data in the ELF file. Maybe you want strip(1)
Recall that ELF is quite a complex and versatile format, it specifies the starting address, the interpreter (ld-linux(8) dynamic linker), the several segments of the program etc. All this meta-data is needed by the kernel for execve(2) and is lost with objcopy -O binary ...
When you use objcopy -O binary, you are copying only the binary data:
objcopy can be used to generate a raw binary file by using an output target of `binary' (e.g., use -O binary). When objcopy generates a raw binary file, it will essentially produce a memory dump of the contents of the input object file. All symbols and relocation information will be discarded. The memory dump will start at the load address of the lowest section copied into the output file.
In particular you lose the entry point and the segments list given in the original ELF header. The kernel cannot guess them.
I don't understand why you expect the result of objcopy -O binary to be executable by Linux using execve(2). The main purpose of that objcopy -O binary command is to make firmware or kernel-like stand-alone (or freestanding) binaries, and then you need to exactly understand how they should look like (e.g. what is their starting point, how they are loaded and started) and you probably also use some very specific linker script, and of course that binary cannot contain any syscall to the linux kernel (in particular cannot do any kind of input or output the way a plain Linux executable does them).
Read also more about ABIs, the x86-64 ABI, the Linux Assembly HowTo, the Advanced Linux Programming book.
You probably should read a good OS textbook like Operating System: Three Easy Pieces.
I'm passing a tar command to shell executor in an application. But it seems that my tar syntax is incorrect. (This is Windows (bsdtar command) but works the same as Linux as far as I know; I can also test on Linux if need be.)
I'm trying to tar gz everything up all files ending in ext without storing the full path in my tar file.
tar -cvzf test.tar.gz -C C:/mydir/toTar/ *.ext
I get an error:
tar: *.ext: Cannot stat: No such file or directory
I can give the whole path but then my tar will contain C->mydir->toTar->. I just want the files, not mydir and toTar in the result.
So far only thing that is close to what I want is . instead of *.ext, but that tars other things too, which I obviously don't want.
The problem is that * is a wildcard character that is expanded by the shell, but you are bypassing the shell and calling tar directly. The tar command is looking for one file which is named literally *.ext and it does not exist.
Your options are:
Expand the list of files in your own code and pass that list to tar.
Call the shell from your code by calling something like /bin/sh -c tar ...
With option 2 there may be security implications -- if the shell sees something it thinks is a command, it will run it. Option 1 is therefore safer, but it's up to you which makes more sense.
I am befuddled by how you're using dos-style paths in an apparently linux-like context. But this is how I'd do it. Hopefully the concept is clear if the details may be incorrect.
cd C:/mydir/toTar/
mkdir ~/tmpwork
find . -name '*.ext' > ~/tmpwork/extfiles
tar czvfT ~/tmpwork/test.tar.gz ~/tmpwork/extfiles
rm ~/tmpfiles/extfiles
There is no way around the shell expansion without using pipes, etc.
I'm on Ubuntu and a certain .so file generated is executable. When I hit tab to autocomplete I get "something.so main.executable" instead of just "main.executable" which is a bit of an annoyance.
Is there a flag to pass to the linker to avoid the chmod or do I have to manually chmod -x after the fact?
How does one find out what is the lib that the above flag is referring to?
How would I do it for some other one?
The -l option takes the name of the library as the argument so in this case the library would be named libXi.a (or libXi.so or something similar). To find the library look in the standard library locations (/usr/lib, /lib, /usr/local/lib, etc.) available in your distribution. There may also be additional library directories specified using the -L option to the linker.
If your program compiled successfully, or if you have another program which uses -lXi, then you can do:
ldd /path/to/that/program | grep libXi
For example:
$ ldd /usr/X11R6/bin/audacity | grep libXi
libXinerama.so.1 => /usr/lib/libXinerama.so.1 (0x00007f53faaba000)
libXi.so.6 => /usr/lib/libXi.so.6 (0x00007f53f8e2c000)
And that will most likely tell you where that library is. (It's not 100% because the build process could alter the search path but that's usually not likely for standard libraries like X11.)
From there, you can ask your distro which package has that file, if you care. For example on Ubuntu or a .deb-base distro:
$ dpkg --search /usr/lib/libXi.so.6
libxi6: /usr/lib/libXi.so.6
If you can't use LDD, then check your system's /etc/ld.so.conf which will indicate the search path for runtime shared library linking. (/lib/ and /usr/lib are included by default.)
Worst case, you could just find for it:
find / -regex '.*libXi\.\(a\|so\).*' 2> /dev/null
strace -f -e open gcc ... -lXi
Look for libXi in the output.