Linking against an existing binary - gcc

I'm working on a project which aims to modify a Pentax DSLR's firmware in order to provide additional functionality.
As part of this I'm writing/documenting the existing camera's API in C.
I can compile my own code using these API's providing it isn't linked into an ELF binary.
In order for this code to run I need to link it with the existing bare metal firmware. A process that I perform manually by copying the object code into the existing binary and fixing the branch instructions.
Is it possible to use the existing GNU toolchain to link against a pre-existing binary and make the manual process automatic.
I can guess that I would need to provide the following:
an offset into the existing binary file to use as a base address
the addresses for all the undefined symbols
I can't see these options in GNU LD.
Is it possible to link a against an existing binary file?

AFAIK re-linking of a binary file is not possible.
Linking is actually the step that creates the binary and therefore re-linking of a binary is not possible.
If you could gather the objects files (the product of assembler) you may be able to create a new binary file.
For more information regarding the build process: http://www.tenouk.com/ModuleW.html

Related

Make: Prioritize -L (or: Ignore contents delivered by pkg-config)

I want to make a library that depends on other libraries.
I have been able to make the static .a files of the dependencies and have them along with the header files readily available in a directory. Running them through file confirms that I have successfully compiled these for all architectures.
When I try to make the final library, it tells me
ld: warning: ignoring file /usr/local....dylib, building for architecture-A but attempting to link with file built for architecture-B
It is correct that the library under the mentioned path is only compiled for the host architecture A (installed via package manager). However, in the LDFLAGS I have -L${libdir}/libs (the folder where the libs are) but make only seems to care about the ones in my usr/local/..folder.
Are there other ways to specifically point make to check the {libdir}/libs folder or even make make ignore the paths from pkg-config in case it searches there first, finds the unfit files and never gets to try the ones I passed in my LDFLAGS?
You write ...
I have been able to make the static .a files of the dependencies and have them along with the header files readily available in a directory.
... but this is probably irrelevant because you seem to be trying to build a shared (i.e. dynamic) library. Static libraries and shared ones don't mix very well.
Are there other ways to specifically point make to check the {libdir}/libs folder or even make make ignore the paths from pkg-config in case it searches there first, finds the unfit files and never gets to try the ones I passed in my LDFLAGS?
You are focusing on make, but make doesn't have much to do with it. It is the linker, not make, that performs the search and the actual link. make just executes the link command you told it to execute.
But yes, you can control the linker's library search order by controlling the order of its command-line options. Library directories specified via -L options are searched in the order they appear on the command line, and all of them before the linker's default library directories.* If ensuring a proper order of arguments does not get you the link you want then it is very likely because the linker is ignoring your static libraries because it is trying to build a dynamic one.
However you should be able to bypass the search altogether by specifying a full path and filename of the library you want to link instead of using -L or -l options. For example, instead of -L/path/to -lfoo, you might use /path/to/libfoo.dylib (or /path/to/libfoo.a). You don't normally want to hardcode paths like that, but in this case it might serve a diagnostic purpose to do so.
Note also that it is rarely a good idea to link against dynamic libraries that are not installed in their intended location, especially if the libraries are not part of the same project. It may seem at first to work ok, but it contributes to problems with finding the libraries at runtime (and dynamic libraries do need to be found at runtime, too). The same does not apply to static libraries, but that comes with its own set of advantages and disadvantages.
* There's more to it than that, but this answer is already long. Read the linker docs if you want more detail.

device tree generation for embedded linux on Zedboard

I am working on ZedBoard(having Zync series SoC from Xilinx) and want to create a device tree for the embedded linux which i am planning to boot on this Zedboard. I followed the two links
http://xillybus.com/tutorials/device-tree-zynq-1
http://www.wiki.xilinx.com/Build+Device+Tree+Blob
They both gave me insight of device tree.
Now I have two options:
I got one prebuilt device tree .dts file for the Zedboard. So, can I use this directly without changing anything and only add mine needed drivers in this and it will work?
or
Should i start from scratch and generate mine own device tree .dts file.
What i want to ask/confirm that: device tree(.dts) file is not project specific and the content of .dts file will be unique for the particular board(which is in our case is ZedBoard). So i can take one working .dts file(as in option 1) as a basic platform for mine project and add mine device node in this .dts file (if it is not there) and it will work?
Please suggest and correct me.
I agree with the #sawdust's comment. Please find the pictorial representation of the same.
I have shamelessly copied it from the presentation here.
To answer your question, you should create your own ".dts" file which includes all the necessary parents (i.e. SOC specific and needed) dtsi files. And compile your ".dts" file using DTC compiler (either from linux/scripts/dtc/dtc in Linux Source tree or by using the package like "device-tree-compiler").
In most cases you can modify the existing device tree file and re-compile it for your purpose. For your case, I think you can have to modify this zynq-zed.dts.

Gcc dead code removal with specific functions used

Lets say I have a large library liblarge, and application app which links to liblarge.
Liblarge is under the LGPL license, and app is under a proprietary one. I'd like to be able to remove all "dead code" from liblarge which is not used from app. Can I do this somehow? Provide a list of used functions to the linker perhaps?
There is no easy way for you to proceed.
You can use the above technique (in my comment) on a private copy to workout which *.o you can remove. Then you can build your own modified liblarge source tree that builds DSO/DLL but removes the *.o from the linker command line (for building the DSO/DLL) after you worked out you did not need.
This is just how C/C++ works a lot of information is lost once code is turned into object code.
For example you might then wish to try and reduce the size of each *.o file. The main way to do that is to split up .c/.cpp compilation units.
The problem with the C/C++ ABIs is that the compiler is free to put code anywhere in the *.o file and then jump into and out of segments inside it using relative offsets. There is not enough metadata saved in the *.o to be able to take apart compiled code and see all the dependencies it requires to function. To do this you need to manually split up the input source code.
This is one reason why for embedded software development when memory footprint used to be important you would literally put one function in inside on source file. These days embedded systems have a lot of memory.

Architecturally what is the difference between a shared object (SO) and a dynamic link library (DLL)?

The question is pretty much in the title: in terms of OS-level implementation, how are shared objects and dlls different?
The reason I ask this is because I recently read this page on extending Python, which states:
Unix and Windows use completely different paradigms for run-time loading of code. Before you try to build a module that can be dynamically loaded, be aware of how your system works.
In Unix, a shared object (.so) file contains code to be used by the program, and also the names of functions and data that it expects to find in the program. When the file is joined to the program, all references to those functions and data in the file’s code are changed to point to the actual locations in the program where the functions and data are placed in memory. This is basically a link operation.
In Windows, a dynamic-link library (.dll) file has no dangling references. Instead, an access to functions or data goes through a lookup table. So the DLL code does not have to be fixed up at runtime to refer to the program’s memory; instead, the code already uses the DLL’s lookup table, and the lookup table is modified at runtime to point to the functions and data.
Could anyone elaborate on that? Specifically I'm not sure I understand the description of shared objects containing references to what they expect to find. Similarly, a DLL sounds like pretty much the same mechanism to me.
Is this a complete explanation of what is going on? Are there better ones? Is there in fact any difference?
I am aware of how to link to a DLL or shared object and a couple of mechanisms (.def listings, dllexport/dllimport) for writing DLLs so I'm explicitly not looking for a how to on those areas; I'm more intrigued as to what is going on in the background.
(Edit: another obvious point - I'm aware they work on different platforms, use different file types (ELF vs PE), are ABI-incompatible etc...)
A Dll is pretty much the same mechanism as used by .so or .dylib (MacOS) files, so it is very hard to explain exactly what the differences are.
The core difference is in what is visible by default from each type of file. .so files export the language (gcc) level linkage - which means that (by default) all C & c++ symbols that are "extern" are available for linking when .so's are pulled in.
It also means that, as resolving .so files is essentially a link step, the loader doesn't care which .so file a symbol comes from. It just searches the specified .so files in some order following the usual link step rules that .a files adhere to.
Dll files on the other hand are an Operating system feature, completely separate to the link step of the language. MSVC uses .lib files for linking both static, and dynamic libraries (each dll file generates a paired .lib file that is used for linking) so the resulting program is fully "linked" (from a language centric point of view) once its built.
During the link stage however, symbols were resolved in the lib's that represents the Dlls, allowing the linker to build the import table in the PE file containing an explicit list of dlls and the entry points referenced in each dll. At load time, Windows does not have to perform a "link" to resolving symbols from shared libraries: That step was already done - the windows loader just loads up the dll's and hooks up the functions directly.

How to put version information in a multi platform program *nix and win32?

I want to know what is the standard way of doing it.
currently I'm thinking in add a series of defines in a header file and inlcudie that file in the main resource file win win32 to update the version resource in win32 and in *nix make some global functions to return this information.
and in windows make the msi install file also reflect the same version.
That sounds like a reasonable way to do it. I don't think there IS a standard way of doing this; there aren't any real standards for version reporting that are cross-platform.
Since we wanted to avoid the overhead of changing a "version.cpp" or equivalent every time we hit build -- and thereby taking the time to do at least one compile and link -- we modify the binary after the build.
If you're outputting to e.g. ELF or PE format executables, you can use some basic knowledge of ELF or PE and a linker map to figure out what to replace, otherwise you can scan through the binary looking for a set pattern (we use something like static const char VERSION[] = "[VERSIONBLOCK xxxxxxxxxxxxx]";) and replace a portion (e.g. the xxxx part above) with relevant info:
build date and time
build machine
username
output of e.g. svnversion
Note that this won't work very well if your binaries are signed or compressed before this step, but usually you can engineer your build process so the signing/compressing happens after this step.
I'm sure a variant of this could be extended to hit the Win32 PE version metadata as well as any embedded version string.

Resources