ELF is a common lisp library for the manipulation of ELF files, which can be used to read, inspect, modify and write elf files.
The code is available under the GNU General Public License.
Source:
http://github.com/eschulte/elf.
*class*
*endian*
*single-value-objdump-hack*
addralign
address
align
alignment
arm-data
arm-instruction
b/bl
binding
bits-at-ea
bits-to-int
bx
bytes-to-int
copy-elf
csurf
csurf-cmd
csurf-script
data
data-processing
disassemblable
disassemble-section
elf
elf
elf-const
elf-header
elf-header
elf-p
entry
entsize
file-offset-of-ea
filesz
flags
from-bits
from-bytes
generic-copy
header
index-of-ea
info
insert
instruction
int-to-bits
int-to-bytes
ldm/stm
ldr/str
link
magic-number
make-arm-branch
make-arm-data-processing
make-arm-data-transfer
make-arm-stack
make-arm-word
mapslots
memsz
name
named-section
named-symbol
objdump
objdump
objdump-cmd
objdump-const
objdump-parse
offset
opcode
operands
ordering
other
paddr
ph
program-table
ptr
read-elf
read-value
rel-info
rel-sym
rel-type
section-holding-ea
section-holding-off
section-table
sections
sections-holding-ea
sections-holding-off
set-arm-branch
set-arm-data-processing
set-arm-data-transfer
set-arm-stack
set-arm-word
sh
shndx
show-dynamic
show-file-layout
show-memory-layout
show-symbols
size
subseq-ea
subseq-off
sym-name
symbols
to-bits
to-bytes
type
un-type
vaddr
val
value
vma
word-at-ea
word-at-off
write-elf
write-value
See ELF.txt for more information on the elf format.
Much of the code in elf.lisp
is a direct translation of the elf
data structures described in the ELF.txt document augmented with
specific information translated from /usr/include/elf.h
.
First load the up the elf
library.
(require :elf)
(in-package :elf)
For the remainder of this example, we’ll use a simple elf binary executable named =hello=, compiled from the following C code.
echo 'main(){puts("hello world");}'|gcc -x c - -o hello
We can check that this is indeed an elf file by checking the magic number at the start of the file.
(elf-p "hello") ; => T
We can also view an elf files header information without parsing the entire file.
(elf::show-it (elf-header "hello") :out nil)
Then we read the binary file into an elf object.
(defvar *elf* (read-elf "hello"))
Using the show-it
function from the elf package we can inspect
the header at the top of the elf file.
(elf::show-it (header *elf*) :out nil)
We can list the names of the sections of the elf file.
(mapcar #'name (sections *elf*))
;; => ("" ".interp" ".note.ABI-tag" ".note.gnu.build-id"...
We can list the segments in the program table, and view both the layout of the elements of the elf file, both in it’s binary file and when it is an executable image in memory.
;; looking at the program table
(mapc #'elf::show-it (program-table *elf*))
TYPE:PHDR FLAGS:5 OFFSET:64 VADDR:4194368 PADDR:4194368 FILE...
TYPE:INTERP FLAGS:4 OFFSET:512 VADDR:4194816 PADDR:4194816 F...
TYPE:LOAD FLAGS:5 OFFSET:0 VADDR:4194304 PADDR:4194304 FILES...
TYPE:LOAD FLAGS:6 OFFSET:1744 VADDR:6293200 PADDR:6293200 FI...
TYPE:DYNAMIC FLAGS:6 OFFSET:1768 VADDR:6293224 PADDR:6293224...
TYPE:NOTE FLAGS:4 OFFSET:540 VADDR:4194844 PADDR:4194844 FIL...
TYPE:GNU_EH_FRAME FLAGS:4 OFFSET:1472 VADDR:4195776 PADDR:41...
TYPE:GNU_STACK FLAGS:6 OFFSET:0 VADDR:0 PADDR:0 FILESZ:0 MEM...
;; view the contents of elf, as they exist in the file
(show-file-layout *elf*)
START OFFSET CONTENTS END
0 NONE HEADER 64
64 NONE PROGRAM-TABLE 512
512 512 .interp 540
540 540 .note.ABI-tag 572
572 572 .note.gnu.build-id 608
608 608 .gnu.hash 636
636 NONE FILLER 640
640 640 .dynsym 736
736 736 .dynstr 797
...
;; view the contents of elf, as they exist in the file
(show-memory-layout *elf*)
addr contents end
-------------------------------------
0x400000 LOAD 0x4006CC
0x400040 PHDR 0x400200
0x400200 INTERP 0x40021C
0x400200 .interp 0x40021C
0x40021C NOTE 0x400260
0x40021C .note.ABI-tag 0x40023C
...
We can write out the elf file to disk.
;; write out the elf file, the results should be identical to
;; the original
(write-elf *elf* "hello2")
The resulting file will be identical to the original file from which the elf object was read.
diff hello hello2
We can manipulate these elf objects, and then write the results
back out to disk. For example we can change the code in the
.text
section of the file, and then write the results back out to
disk.
;; change the .text section -- this doesn't break the program
(aref (data (named-section *elf* ".text")) 40) ; => 144
(setf (aref (data (named-section *elf* ".text")) 40) #xc3)
(aref (data (named-section *elf* ".text")) 40) ; => 195
;; When we write the modified elf to a file, the resulting file
;; will be different than the original hello (in one byte) but
;; will still execute since we changed a byte off of the
;; execution path
(write-elf *elf* "hello2")
Meta information like the relevant program and section headers, as
well as symbol information in the .dynamic
section of the file
will be automatically updated.
(let ((text (named-section *elf* ".text")))
(setf (data text)
(concatenate 'vector
(data text)
(make-array 16 :initial-element #x90))))
(write-elf *elf* "hello3")
Note however that the resulting file will segfault on evaluation, because even though the meta-data of the elf file is updated automatically, there are hard-coded offsets and memory locations in the compiled data contained in the elf file, which can not be automatically updated.
[Special variable]
*class*
Word size of the machine, (e.g. :32-bit or :64-bit).
[Special variable]
*endian*
Controls the endianness of how bytes are read.
[Special variable]
*single-value-objdump-hack*
Set to non-nil if objdump prints 4-byte values as a single number.
[Generic accessor]
addralign object => result
(setf (addralign object) new-value)
[Specialized accessor]
addralign (object section-header) => result
(setf (addralign (object section-header)) new-value)
automatically generated reader method
[Generic accessor]
address object => result
(setf (address object) new-value)
[Specialized accessor]
address (object section-header) => result
(setf (address (object section-header)) new-value)
automatically generated reader method
[Generic accessor]
align object => result
(setf (align object) new-value)
[Specialized accessor]
align (object program-header-64) => result
(setf (align (object program-header-64)) new-value)
automatically generated reader method
[Specialized accessor]
align (object program-header-32) => result
(setf (align (object program-header-32)) new-value)
automatically generated reader method
[Generic accessor]
alignment section => result
(setf (alignment section) new)
[Specialized accessor]
alignment (section section) => result
(setf (alignment (section section)) new)
[Standard class]
arm-data
[Standard class]
arm-instruction
[Standard class]
b/bl
[Generic accessor]
binding sym => result
(setf (binding symbol) new)
[Specialized accessor]
binding (sym elf-sym) => result
(setf (binding (symbol elf-sym)) new)
[Generic accessor]
bits-at-ea obj ea => result
(setf (bits-at-ea obj ea) new)
[Specialized accessor]
bits-at-ea (obj elf) ea => result
(setf (bits-at-ea (obj elf) ea) new)
[Specialized accessor]
bits-at-ea (obj section) ea => result
(setf (bits-at-ea (obj section) ea) new)
[Function]
bits-to-int bits &optional signed-p => result
[Standard class]
bx
[Function]
bytes-to-int bytes &optional signed-p byte-size &aux steps => result
[Function]
copy-elf elf => result
[Standard class]
csurf
[Special variable]
csurf-cmd
[Special variable]
csurf-script
[Generic accessor]
data object => result
(setf (data section) new)
[Method]
data (object section) => result
automatically generated reader method
[Standard class]
data-processing
[Standard class]
disassemblable
[Generic function]
disassemble-section disassemblable section => result
Return the disassembly of the contents of SECTION in DISASSEMBLABLE. The contents are returned grouped by function.
[Standard class]
elf
[Generic accessor]
elf object => result
(setf (elf object) new-value)
[Specialized accessor]
elf (object section) => result
(setf (elf (object section)) new-value)
automatically generated reader method
[Standard class]
elf-const
Disassemblable objects with caches holding disassembly by section name.
[Standard class]
elf-header
[Function]
elf-header file => result
[Function]
elf-p file => result
Return t if file is an ELF file (using the magic number test).
[Generic accessor]
entry object => result
(setf (entry object) new-value)
[Specialized accessor]
entry (object elf-header) => result
(setf (entry (object elf-header)) new-value)
automatically generated reader method
[Generic accessor]
entsize object => result
(setf (entsize object) new-value)
[Specialized accessor]
entsize (object section-header) => result
(setf (entsize (object section-header)) new-value)
automatically generated reader method
[Generic function]
file-offset-of-ea elf ea => result
Return the file offset in ELF of EA.
[Generic accessor]
filesz object => result
(setf (filesz object) new-value)
[Specialized accessor]
filesz (object program-header-64) => result
(setf (filesz (object program-header-64)) new-value)
automatically generated reader method
[Specialized accessor]
filesz (object program-header-32) => result
(setf (filesz (object program-header-32)) new-value)
automatically generated reader method
[Generic accessor]
flags object => result
(setf (flags object) new-value)
[Specialized accessor]
flags (object section) => result
(setf (flags (object section)) new-value)
[Specialized accessor]
flags (object program-header-64) => result
(setf (flags (object program-header-64)) new-value)
automatically generated reader method
[Specialized accessor]
flags (object program-header-32) => result
(setf (flags (object program-header-32)) new-value)
automatically generated reader method
[Specialized accessor]
flags (object section-header) => result
(setf (flags (object section-header)) new-value)
automatically generated reader method
[Specialized accessor]
flags (object elf-header) => result
(setf (flags (object elf-header)) new-value)
automatically generated reader method
[Generic function]
from-bits obj bits => result
[Method]
from-bits (obj arm-data) bits => result
[Generic function]
from-bytes obj bytes => result
[Method]
from-bytes (obj arm-data) bytes => result
[Function]
generic-copy obj &optional trace => result
A generic copy method, may run way too long on partially circular elements.
[Generic accessor]
header object => result
(setf (header object) new-value)
[Specialized accessor]
header (object elf) => result
(setf (header (object elf)) new-value)
automatically generated reader method
[Generic function]
index-of-ea obj ea => result
[Method]
index-of-ea (obj section) ea => result
[Generic accessor]
info object => result
(setf (info object) new-value)
[Specialized accessor]
info (object elf-sym-64) => result
(setf (info (object elf-sym-64)) new-value)
automatically generated reader method
[Specialized accessor]
info (object elf-sym-32) => result
(setf (info (object elf-sym-32)) new-value)
automatically generated reader method
[Specialized accessor]
info (object elf-rela-64) => result
(setf (info (object elf-rela-64)) new-value)
automatically generated reader method
[Specialized accessor]
info (object elf-rela-32) => result
(setf (info (object elf-rela-32)) new-value)
automatically generated reader method
[Specialized accessor]
info (object elf-rel-64) => result
(setf (info (object elf-rel-64)) new-value)
automatically generated reader method
[Specialized accessor]
info (object elf-rel-32) => result
(setf (info (object elf-rel-32)) new-value)
automatically generated reader method
[Specialized accessor]
info (object section-header) => result
(setf (info (object section-header)) new-value)
automatically generated reader method
[Generic function]
insert obj data ea => result
Write DATA into OBJ at EA overwriting previous contents.
[Standard class]
instruction
[Function]
int-to-bits byte size &optional signed-p => result
[Function]
int-to-bytes int size &optional signed-p byte-size &aux steps => result
[Standard class]
ldm/stm
[Standard class]
ldr/str
[Generic accessor]
link object => result
(setf (link object) new-value)
[Specialized accessor]
link (object section-header) => result
(setf (link (object section-header)) new-value)
automatically generated reader method
[Generic accessor]
magic-number object => result
(setf (magic-number object) new-value)
[Specialized accessor]
magic-number (object elf-header) => result
(setf (magic-number (object elf-header)) new-value)
automatically generated reader method
[Function]
make-arm-branch mnemonic offset => result
[Function]
make-arm-data-processing mnemonic register immediate => result
[Function]
make-arm-data-transfer mnemonic reg offset => result
[Function]
make-arm-stack mnemonic registers => result
[Function]
make-arm-word immediate => result
[Function]
mapslots func obj => result
Map func over the slots of the clos object OBJ.
[Generic accessor]
memsz object => result
(setf (memsz object) new-value)
[Specialized accessor]
memsz (object program-header-64) => result
(setf (memsz (object program-header-64)) new-value)
automatically generated reader method
[Specialized accessor]
memsz (object program-header-32) => result
(setf (memsz (object program-header-32)) new-value)
automatically generated reader method
[Generic accessor]
name object => result
(setf (name object) new-value)
[Specialized accessor]
name (object section) => result
(setf (name (object section)) new-value)
automatically generated reader method
[Specialized accessor]
name (object elf-sym-64) => result
(setf (name (object elf-sym-64)) new-value)
automatically generated reader method
[Specialized accessor]
name (object elf-sym-32) => result
(setf (name (object elf-sym-32)) new-value)
automatically generated reader method
[Specialized accessor]
name (object section-header) => result
(setf (name (object section-header)) new-value)
automatically generated reader method
[Function]
named-section elf name => result
Return the section in ELF named NAME.
[Function]
named-symbol elf name => result
Return the symbol in ELF named NAME.
[Standard class]
objdump
[Function]
objdump section => result
[Special variable]
objdump-cmd
Name of the objdump executable.
[Standard class]
objdump-const
Caching objdump-backed ELF file.
[Function]
objdump-parse output => result
Parse the output ofobjdump
returning the disassembly by symbol.
[Generic accessor]
offset object => result
(setf (offset object) new-value)
[Specialized accessor]
offset (object b/bl) => result
(setf (offset (object b/bl)) new-value)
automatically generated reader method
[Specialized accessor]
offset (object ldr/str) => result
(setf (offset (object ldr/str)) new-value)
automatically generated reader method
[Specialized accessor]
offset (object section) => result
(setf (offset (object section)) new-value)
[Specialized accessor]
offset (object elf-rela-64) => result
(setf (offset (object elf-rela-64)) new-value)
automatically generated reader method
[Specialized accessor]
offset (object elf-rela-32) => result
(setf (offset (object elf-rela-32)) new-value)
automatically generated reader method
[Specialized accessor]
offset (object elf-rel-64) => result
(setf (offset (object elf-rel-64)) new-value)
automatically generated reader method
[Specialized accessor]
offset (object elf-rel-32) => result
(setf (offset (object elf-rel-32)) new-value)
automatically generated reader method
[Specialized accessor]
offset (object program-header-64) => result
(setf (offset (object program-header-64)) new-value)
automatically generated reader method
[Specialized accessor]
offset (object program-header-32) => result
(setf (offset (object program-header-32)) new-value)
automatically generated reader method
[Specialized accessor]
offset (object section-header) => result
(setf (offset (object section-header)) new-value)
automatically generated reader method
[Generic accessor]
opcode object => result
(setf (opcode object) new-value)
[Specialized accessor]
opcode (object instruction) => result
(setf (opcode (object instruction)) new-value)
automatically generated reader method
[Specialized accessor]
opcode (object data-processing) => result
(setf (opcode (object data-processing)) new-value)
automatically generated reader method
[Generic accessor]
operands object => result
(setf (operands object) new-value)
[Specialized accessor]
operands (object instruction) => result
(setf (operands (object instruction)) new-value)
automatically generated reader method
[Generic accessor]
ordering object => result
(setf (ordering object) new-value)
[Specialized accessor]
ordering (object elf) => result
(setf (ordering (object elf)) new-value)
automatically generated reader method
[Generic accessor]
other object => result
(setf (other object) new-value)
[Specialized accessor]
other (object elf-sym-64) => result
(setf (other (object elf-sym-64)) new-value)
automatically generated reader method
[Specialized accessor]
other (object elf-sym-32) => result
(setf (other (object elf-sym-32)) new-value)
automatically generated reader method
[Generic accessor]
paddr object => result
(setf (paddr object) new-value)
[Specialized accessor]
paddr (object program-header-64) => result
(setf (paddr (object program-header-64)) new-value)
automatically generated reader method
[Specialized accessor]
paddr (object program-header-32) => result
(setf (paddr (object program-header-32)) new-value)
automatically generated reader method
[Generic accessor]
ph object => result
(setf (ph object) new-value)
[Specialized accessor]
ph (object section) => result
(setf (ph (object section)) new-value)
automatically generated reader method
[Generic accessor]
program-table object => result
(setf (program-table object) new-value)
[Specialized accessor]
program-table (object elf) => result
(setf (program-table (object elf)) new-value)
automatically generated reader method
[Generic accessor]
ptr dyn => result
(setf (ptr dyn) new)
[Specialized accessor]
ptr (dyn elf-dyn) => result
(setf (ptr (dyn elf-dyn)) new)
[Function]
read-elf file &optional type => result
[Generic function]
read-value type stream &key arm-instruction length value bytes byte-size terminator swap character-type bits-per-byte => result
Read a value of the given type from the stream.
[Function]
rel-info sym type => result
Convert a symbol and type back into the info field of an elf-rel.
[Generic function]
rel-sym rel => result
Shift bits in REL based on its class.
[Generic function]
rel-type rel header => result
The interpretation of the type is machine specific.
[Function]
section-holding-ea obj ea-start &optional ea-end => result
[Function]
section-holding-off obj off-start &optional off-end => result
[Generic accessor]
section-table object => result
(setf (section-table object) new-value)
[Specialized accessor]
section-table (object elf) => result
(setf (section-table (object elf)) new-value)
automatically generated reader method
[Generic accessor]
sections object => result
(setf (sections object) new-value)
[Specialized accessor]
sections (object elf) => result
(setf (sections (object elf)) new-value)
automatically generated reader method
[Function]
sections-holding-ea elf ea-start &optional ea-end => result
[Function]
sections-holding-off elf off-start &optional off-end => result
Return the section holding the requested file locations. Note, this does not return filler if the requested file location is just filler bytes.
[Generic function]
set-arm-branch obj mnemonic to from => result
[Method]
set-arm-branch (obj elf) mnemonic to from => result
[Generic function]
set-arm-data-processing obj mnemonic place register immediate => result
[Method]
set-arm-data-processing (obj elf) mnemonic place register immediate => result
[Generic function]
set-arm-data-transfer obj mnemonic place reg from => result
[Method]
set-arm-data-transfer (obj elf) mnemonic place reg from => result
[Generic function]
set-arm-stack obj mnemonic place registers => result
[Method]
set-arm-stack (obj elf) mnemonic place registers => result
[Generic function]
set-arm-word obj place immediate => result
[Method]
set-arm-word (obj elf) place immediate => result
[Generic accessor]
sh object => result
(setf (sh object) new-value)
[Specialized accessor]
sh (object section) => result
(setf (sh (object section)) new-value)
automatically generated reader method
[Generic accessor]
shndx object => result
(setf (shndx object) new-value)
[Specialized accessor]
shndx (object elf-sym-64) => result
(setf (shndx (object elf-sym-64)) new-value)
automatically generated reader method
[Specialized accessor]
shndx (object elf-sym-32) => result
(setf (shndx (object elf-sym-32)) new-value)
automatically generated reader method
[Function]
show-dynamic elf => result
Show the dynamic symbols of ELF in a manner similar to readelf.
[Function]
show-file-layout elf => result
Show the layout of the elements of an elf file with binary offset.
[Function]
show-memory-layout elf => result
Show the layout of the elements of an elf file with binary offset.
[Function]
show-symbols elf => result
Show all symbols in ELF in a manner similar to readelf.
[Generic accessor]
size object => result
(setf (size object) new-value)
[Specialized accessor]
size (object section) => result
(setf (size (object section)) new-value)
[Specialized accessor]
size (object elf-sym-64) => result
(setf (size (object elf-sym-64)) new-value)
automatically generated reader method
[Specialized accessor]
size (object elf-sym-32) => result
(setf (size (object elf-sym-32)) new-value)
automatically generated reader method
[Specialized accessor]
size (object section-header) => result
(setf (size (object section-header)) new-value)
automatically generated reader method
[Generic accessor]
subseq-ea obj ea-start &optional ea-end => result
(setf (subseq-ea obj ea-start &optional ea-end) new)
[Specialized accessor]
subseq-ea (obj section) ea-start &optional ea-end => result
(setf (subseq-ea (obj section) ea-start &optional ea-end) new)
[Specialized accessor]
subseq-ea (obj elf) ea-start &optional ea-end => result
(setf (subseq-ea (obj elf) ea-start &optional ea-end) new)
[Generic accessor]
subseq-off obj off-start &optional off-end => result
(setf (subseq-off obj off-start &optional off-end) new)
[Specialized accessor]
subseq-off (obj section) off-start &optional off-end => result
(setf (subseq-off (obj section) off-start &optional off-end) new)
[Specialized accessor]
subseq-off (obj elf) off-start &optional off-end => result
(setf (subseq-off (obj elf) off-start &optional off-end) new)
[Generic accessor]
sym-name object => result
(setf (sym-name object) new-value)
[Specialized accessor]
sym-name (object elf-sym) => result
(setf (sym-name (object elf-sym)) new-value)
automatically generated reader method
[Generic function]
symbols elf => result
Return the symbols contained in ELF.
[Generic function]
to-bits obj => result
[Method]
to-bits (obj arm-data) => result
[Generic function]
to-bytes obj => result
[Method]
to-bytes (obj arm-data) => result
[Generic accessor]
type object => result
(setf (type object) new-value)
[Specialized accessor]
type (object section) => result
(setf (type (object section)) new-value)
[Specialized accessor]
type (object elf-sym) => result
(setf (type (object elf-sym)) new-value)
[Specialized accessor]
type (object program-header-64) => result
(setf (type (object program-header-64)) new-value)
automatically generated reader method
[Specialized accessor]
type (object program-header-32) => result
(setf (type (object program-header-32)) new-value)
automatically generated reader method
[Specialized accessor]
type (object section-header) => result
(setf (type (object section-header)) new-value)
automatically generated reader method
[Specialized accessor]
type (object elf-header) => result
(setf (type (object elf-header)) new-value)
automatically generated reader method
[Generic function]
un-type dyn => result
[Method]
un-type (dyn elf-dyn) => result
[Generic accessor]
vaddr object => result
(setf (vaddr object) new-value)
[Specialized accessor]
vaddr (object program-header-64) => result
(setf (vaddr (object program-header-64)) new-value)
automatically generated reader method
[Specialized accessor]
vaddr (object program-header-32) => result
(setf (vaddr (object program-header-32)) new-value)
automatically generated reader method
[Generic accessor]
val dyn => result
(setf (val dyn) new)
[Specialized accessor]
val (dyn elf-dyn) => result
(setf (val (dyn elf-dyn)) new)
[Generic accessor]
value object => result
(setf (value object) new-value)
[Specialized accessor]
value (object elf-sym-64) => result
(setf (value (object elf-sym-64)) new-value)
automatically generated reader method
[Specialized accessor]
value (object elf-sym-32) => result
(setf (value (object elf-sym-32)) new-value)
automatically generated reader method
[Generic accessor]
vma section => result
(setf (vma section) new)
Return the virtual memory address for SECTION.
[Generic accessor]
word-at-ea obj ea => result
(setf (word-at-ea obj ea) new)
[Specialized accessor]
word-at-ea (obj elf) ea => result
(setf (word-at-ea (obj elf) ea) new)
[Specialized accessor]
word-at-ea (obj section) ea => result
(setf (word-at-ea (obj section) ea) new)
[Generic accessor]
word-at-off obj off => result
(setf (word-at-off obj off) new)
[Specialized accessor]
word-at-off (obj elf) off => result
(setf (word-at-off (obj elf) off) new)
[Specialized accessor]
word-at-off (obj section) off => result
(setf (word-at-off (obj section) off) new)
[Function]
write-elf elf file => result
[Generic function]
write-value type stream value &key arm-instruction length value bytes byte-size terminator swap character-type bits-per-byte => result
Write a value as the given type to the stream.
[Method]
(setf (vma (section section)) new)
This documentation was prepared with a hacked up version of DOCUMENTATION-TEMPLATE.