The BASH script objembed.sh
handles the process of generating an ELF
object file from a plain text file. It is basically a wrapper around GNU's
objcopy
tool from the binutils
package. objembed.sh
adds some basic
handling of the target architecture.
This project shows how to embed arbitrary plain text in a C project during
compilation and how that text can be accessed during runtime. Hence, the files
embed.c
and, especially, the Makefile act as a showcase project.
In particular, projects written in the C programming language are targeted, as other (i.e. newer) languages may already provide other mechanisms to embed plain text.
As already mentioned objembed.sh
uses objcopy
to convert a text file
filename.ext
into an object file. objcopy
adds the linker symbols
_binary_filename_ext_start
and_binary_filename_ext_end
around the contents of the text file which can then be used in C source code to
extract the text. The resulting object file can be statically linked against a C
project by passing that file directly to the linker. Here, filename
is the
basename of the text file's path without its file name extension ext
. That
means the full basename of the text file is contained in the linker symbols
where the dot (.
) in filename.ext
gets replaced by an underscore (_
)
character: filename_ext
. The text file is read by objcopy
in binary format
for what reason the linker symbols are prefixed with _binary_
. _start
, and
_end
, are appended to the symbols, respectively.
The example code simply embeds a version string into the object code. Obviously, it does not really represent a real use case, because that can easier be achieved by passing a preprocessor macro definition to the compiler. For instance:
$ gcc -o project -DVERSION='"0.1.0"' project.c
The actual version string could be hold in a Makefile variable
(VERSION = '"0.1.0"'
).
Anyway, for example, an API token, or much longer texts, like a license disclaimer, could be embedded during compilation. There are other use cases, as well.
To simply generate an ELF object code file object.o
for a 64-bit
processor architecture from a plain text file text.txt
the following
command is sufficient:
$ bash objembed.sh text.txt object.o 64
objembed.sh
will ask before overwriting an object file. If no architecture
is provided the architecture of the current machine is used.
Note: Currently only 32 bit and 64 bit x86 targets are supported.
Executing objembed.sh
with the --help
flag would print the following
usage information:
objembed version 0.1.0
copyright (c) 2020 Daniel Haase
- embed plain text in object files
usage: objembed.sh <txtfile> <objfile> [<arch>]
objembed.sh [-h | -V]
objembed uses "objcopy" to convert the text file <txtfile>
to an object file <objfile>. "objcopy" adds the linker symbols
"_binary_<filename>_<ext>_start" and
"_binary_<filename>_<ext>_end"
around the contents of <txtfile> which can be used in C code
to extract the text. the resulting <objfile> can be statically
linked against a C project by passing <objfile> directly to
the linker. Here, <filename> is the basename of <txtfile>
without its file name extension <ext> (i.e. the dot ('.') in
"filename.ext" gets replaced by an underscore ('_') character).
<txtfile>
path to text file containing ASCII plain text
to be embedded in <objfile>
<objfile>
object file output filename/path containing the
contents of <txtfile>
<arch>
target machine architecture
(defaults to architecture of current machine)
-h | --help
print this usage information and exit
-V | --version
print version information and exit
Possible exit codes are:
- 0 - success
- 1 - missing dependency
- 2 - not a Linux system
- 3 - invalid command line syntax
- 4 - input file not found
- 5 - unsupported architecture
- 6 - operation failed (objcopy error)
The showcase project can be built and run with:
$ make
$ ./embed
which should print the just compiled-in version number.
The required text file that will be embedded is generated by make
itself.
The script can be permanently installed by running:
$ cp objembed.sh /usr/local/bin/objembed
$ chmod 755 /usr/local/bin/objembed
Of course, instead of copying, a symbolic link can be created, as well:
$ chmod 755 objembed.sh
$ ln -s $(pwd)/objembed.sh /usr/local/bin/objembed
Copyright © 2020 Daniel Haase
Distributed under the Boost Software License, Version 1.0.
See license text below, accompanying file LICENSE, or copy at boost.org.
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.