Helper words for elf

release
Erik Charlebois 2010-04-09 23:45:21 -07:00
parent 1a570a8fc8
commit b86abfb70c
1 changed files with 120 additions and 11 deletions

View File

@ -1,10 +1,11 @@
! Copyright (C) 2010 Erik Charlebois.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors alien alien.c-types alien.strings alien.syntax arrays
classes.struct io.encodings.ascii kernel locals sequences
specialized-arrays strings typed ;
classes.struct io.encodings.ascii kernel locals math math.intervals
sequences specialized-arrays strings typed ;
IN: elf
! FFI data
CONSTANT: EI_NIDENT 16
CONSTANT: EI_MAG0 0
CONSTANT: EI_MAG1 1
@ -459,10 +460,15 @@ STRUCT: Elf64_Dyn
{ d_tag Elf64_Sxword }
{ d_val Elf64_Xword } ;
SPECIALIZED-ARRAYS: Elf32_Shdr Elf64_Shdr uchar ;
! Low-level interface
SPECIALIZED-ARRAYS: Elf32_Shdr Elf64_Shdr Elf32_Sym Elf64_Sym Elf32_Phdr Elf64_Phdr uchar ;
UNION: Elf32/64_Ehdr Elf32_Ehdr Elf64_Ehdr ;
UNION: Elf32/64_Shdr Elf32_Shdr Elf64_Shdr ;
UNION: Elf32/64_Shdr-array Elf32_Shdr-array Elf64_Shdr-array ;
UNION: Elf32/64_Sym Elf32_Sym Elf64_Sym ;
UNION: Elf32/64_Sym-array Elf32_Sym-array Elf64_Sym-array ;
UNION: Elf32/64_Phdr Elf32_Phdr Elf64_Phdr ;
UNION: Elf32/64_Phdr-array Elf32_Phdr-array Elf64_Phdr-array ;
TYPED: 64-bit? ( elf: Elf32/64_Ehdr -- ? )
e_ident>> EI_CLASS swap nth ELFCLASS64 = ;
@ -479,25 +485,128 @@ TYPED:: elf-section-headers ( elf: Elf32/64_Ehdr -- headers: Elf32/64_Shdr-array
[ <direct-Elf64_Shdr-array> ]
[ <direct-Elf32_Shdr-array> ] if ;
TYPED:: elf-program-headers ( elf: Elf32/64_Ehdr -- headers: Elf32/64_Phdr-array )
elf [ e_phoff>> ] [ e_phnum>> ] bi :> ( off num )
off elf >c-ptr <displaced-alien> num
elf 64-bit?
[ <direct-Elf64_Phdr-array> ]
[ <direct-Elf32_Phdr-array> ] if ;
TYPED: elf-loadable-segments ( headers: Elf32/64_Phdr-array -- headers: Elf32/64_Phdr-array )
[ p_type>> PT_LOAD = ] filter ;
TYPED:: elf-segment-sections ( segment: Elf32/64_Phdr sections: Elf32/64_Shdr-array -- sections )
segment [ p_offset>> dup ] [ p_filesz>> + ] bi [a,b) :> segment-interval
sections [ dup [ sh_offset>> dup ] [ sh_size>> + ] bi [a,b) 2array ] { } map-as :> section-intervals
section-intervals [ second segment-interval interval-intersect empty-interval = not ]
filter [ first ] map ;
TYPED:: virtual-address-segment ( elf: Elf32/64_Ehdr address -- program-header/f )
elf elf-program-headers elf-loadable-segments [
[ p_vaddr>> dup ] [ p_memsz>> + ] bi [a,b)
address swap interval-contains?
] filter [ f ] [ first ] if-empty ;
TYPED:: virtual-address-section ( elf: Elf32/64_Ehdr address -- section-header/f )
elf address virtual-address-segment :> segment
segment elf elf-section-headers elf-segment-sections :> sections
address segment p_vaddr>> - segment p_offset>> + :> faddress
sections [
[ sh_offset>> dup ] [ sh_size>> + ] bi [a,b)
faddress swap interval-contains?
] filter [ f ] [ first ] if-empty ;
TYPED:: elf-segment-data ( elf: Elf32/64_Ehdr header: Elf32/64_Phdr -- uchar-array/f )
header [ p_offset>> elf >c-ptr <displaced-alien> ] [ p_filesz>> ] bi <direct-uchar-array> ;
TYPED:: elf-section-data ( elf: Elf32/64_Ehdr header: Elf32/64_Shdr -- uchar-array/f )
header [ sh_offset>> elf >c-ptr <displaced-alien> ] [ sh_size>> ] bi <direct-uchar-array> ;
TYPED:: elf-section-data-by-index ( elf: Elf32/64_Ehdr index -- header/f uchar-array/f )
elf elf-section-headers :> sections
index sections nth :> header
elf header elf-section-data :> data
header data ;
TYPED:: elf-section-name ( elf: Elf32/64_Ehdr header: Elf32/64_Shdr -- name: string )
elf elf e_shstrndx>> elf-section-data-by-index nip >c-ptr :> section-names
header sh_name>> section-names <displaced-alien> ascii alien>string ;
TYPED:: elf-section-data-by-name ( elf: Elf32/64_Ehdr name: string -- header/f uchar-array/f )
elf elf-section-headers :> sections
elf e_shstrndx>> :> ndx
elf ndx sections nth elf-section-data >c-ptr :> section-names
sections 1 tail [
sh_name>> section-names <displaced-alien> ascii alien>string name =
] find nip
[ dup elf swap elf-section-data ]
[ f f ] if* ;
TYPED:: elf-section-names ( elf: Elf32/64_Ehdr -- names )
elf elf-section-headers :> sections
elf ".shstrtab" elf-section-data-by-name nip >c-ptr :> section-names
sections 1 tail [
sh_name>> section-names <displaced-alien>
ascii alien>string
TYPED:: elf-sections ( elf: Elf32/64_Ehdr -- sections )
elf elf-section-headers :> sections
elf elf e_shstrndx>> elf-section-data-by-index nip >c-ptr :> section-names
sections [
[ sh_name>> section-names <displaced-alien>
ascii alien>string ] keep 2array
] { } map-as ;
TYPED:: elf-symbols ( elf: Elf32/64_Ehdr section-data: uchar-array -- symbols )
elf ".strtab" elf-section-data-by-name nip >c-ptr :> strings
section-data [ >c-ptr ] [ length ] bi
elf 64-bit?
[ Elf64_Sym heap-size / <direct-Elf64_Sym-array> ]
[ Elf32_Sym heap-size / <direct-Elf32_Sym-array> ] if
[ [ st_name>> strings <displaced-alien> ascii alien>string ] keep 2array ] { } map-as ;
! High level interface
TUPLE: elf elf-header ;
TUPLE: section name elf-header section-header data ;
TUPLE: segment elf-header program-header data ;
TUPLE: symbol name elf-header sym data ;
GENERIC: sections ( obj -- sections )
: <elf> ( c-ptr -- elf )
elf-header elf boa ;
M:: elf sections ( elf -- sections )
elf elf-header>> elf-sections
[
first2 :> ( name header )
elf elf-header>> header elf-section-data :> data
name elf elf-header>> header data section boa
] { } map-as ;
:: segments ( elf -- segments )
elf elf-header>> elf-program-headers
[| header |
elf elf-header>> header elf-segment-data :> data
elf elf-header>> header data segment boa
] { } map-as ;
M:: segment sections ( segment -- sections )
segment program-header>>
segment elf-header>> elf-section-headers
elf-segment-sections
[| header |
segment elf-header>> header elf-section-name :> name
segment elf-header>> header elf-section-data :> data
name segment elf-header>> header data section boa
] { } map-as ;
:: symbols ( section -- symbols )
section elf-header>>
section data>>
elf-symbols
[
first2 :> ( name sym )
name section elf-header>> sym f symbol boa
] { } map-as ;
:: symbol-data ( symbol -- data )
symbol [ elf-header>> ] [ sym>> st_value>> ] bi virtual-address-segment :> segment
symbol sym>> st_value>> segment p_vaddr>> - segment p_offset>> + :> faddress
faddress symbol elf-header>> >c-ptr <displaced-alien>
symbol sym>> st_size>> <direct-uchar-array> ;