Skip to content

Commit e3f1c63

Browse files
committed
Add support for hexdumping sections by name
1 parent 18c69c9 commit e3f1c63

File tree

4 files changed

+58
-2
lines changed

4 files changed

+58
-2
lines changed

ELFSage/Commands/Read.lean

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ def getSymbolNameInSection
7272
| .ok ste => RawELFFile.symbolNameByLinkAndOffset
7373
elffile (SectionHeaderTableEntry.sh_link shte) (SymbolTableEntry.st_name ste)
7474

75+
--TODO find? might be more appropriate than filter here.
76+
7577
def printSymbolsForSectionType (elffile: RawELFFile) (ent_type : Nat) :=
7678
let ofType := elffile.getRawSectionHeaderTableEntries.filter $ λ⟨shte, _⟩↦
7779
SectionHeaderTableEntry.sh_type shte == ent_type
@@ -88,6 +90,18 @@ def printHexForSectionIdx (elffile : RawELFFile) (idx : Nat) :=
8890
| .none => IO.println s!"There doesn't appear to be a section header {idx}"
8991
| .some ⟨_, sec⟩ => dumpBytesAsHex sec.section_body
9092

93+
def printHexForSectionName (elffile : RawELFFile) (name : String) :=
94+
match elffile.getSectionHeaderStringTable? with
95+
| .error err => IO.println err
96+
| .ok (_,shstrtab_sec) =>
97+
let shstrtab : ELFStringTable := ⟨shstrtab_sec.section_body⟩
98+
let offset := shstrtab.stringToOffset name
99+
let findPred : RawSectionHeaderTableEntry × InterpretedSection → Bool := (λent => SectionHeaderTableEntry.sh_name ent.fst == offset)
100+
let msec := elffile.getRawSectionHeaderTableEntries.find? findPred
101+
match msec with
102+
| .none => IO.println s!"There doesn't appear to be a section header named {name}"
103+
| .some ⟨_, sec⟩ => dumpBytesAsHex sec.section_body
104+
91105
def printHexForSymbolIdx (elffile : RawELFFile) (idx : Nat) :=
92106
match do
93107
let ⟨symshte, symsec⟩ ← elffile.getSymbolTable?
@@ -239,8 +253,10 @@ def runReadCmd (p : Cli.Parsed): IO UInt32 := do
239253
| none => IO.println "couldn't parse section number provided for string dump"
240254
| some idx => printStringsForSectionIdx elffile idx
241255
| "hex-dump" => match flag.as? Nat with
242-
| none => IO.println "couldn't parse section number provided for hex dump"
243256
| some idx => printHexForSectionIdx elffile idx
257+
| none => match flag.as? String with
258+
| some name => printHexForSectionName elffile name
259+
| none => IO.println "couldn't parse section provided for hex dump"
244260
| "sym-dump" => match flag.as? Nat with
245261
| none => IO.println "couldn't parse symbol number provided for hex dump"
246262
| some idx => printHexForSymbolIdx elffile idx

ELFSage/Types/File.lean

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ def RawELFFile.getRawELFHeader : RawELFFile → RawELFHeader
142142
| .elf32 elffile => .elf32 elffile.file_header
143143
| .elf64 elffile => .elf64 elffile.file_header
144144

145+
-- TODO Perhaps just make ELFFile an ELFHeader instance
146+
145147
def RawELFFile.isBigendian (elffile : RawELFFile) := ELFHeader.isBigendian elffile.getRawELFHeader
146148

147149
def RawELFFile.is64Bit (elffile : RawELFFile) := ELFHeader.is64Bit elffile.getRawELFHeader
@@ -156,6 +158,17 @@ def RawELFFile.getSymbolTable? (elffile : RawELFFile)
156158
where noSymTable := .error "No symbol table present, no st_size given, can't guess byte range"
157159
symbolSections := elffile.getRawSectionHeaderTableEntries.filter $ λ⟨shte, _⟩↦
158160
SectionHeaderTableEntry.sh_type shte == ELFSectionHeaderTableEntry.Type.SHT_SYMTAB
161+
162+
/--
163+
Get the section .shstrtab. Defined by e_shstrndx in the ELF header and therefore unique
164+
-/
165+
def RawELFFile.getSectionHeaderStringTable? (elffile : RawELFFile)
166+
: Except String (RawSectionHeaderTableEntry × InterpretedSection) :=
167+
let sections := elffile.getRawSectionHeaderTableEntries
168+
match sections[ELFHeader.e_shstrndx elffile.getRawELFHeader]? with
169+
| none => .error "e_shstrndx in ELF header refers to a nonexistent section"
170+
| some entry => .ok entry
171+
159172
/--
160173
Get the section of type SHT_DYNSYM
161174
There's at most one: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html

ELFSage/Types/StringTable.lean

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,30 @@ def ELFStringTable.stringAt (st : ELFStringTable) (idx : Nat) : String :=
2222
let range := st.strings.extract idx idx₂
2323
let chars := range.toList.map (λbyte => Char.ofNat byte.toNat)
2424
String.mk chars
25+
26+
structure StringTableEntry where
27+
/-- String associated with a string table entry --/
28+
string : String
29+
/-- Offset within the associated string table --/
30+
offset : Nat
31+
deriving Repr
32+
33+
-- Get all the string entries in an ELFStringTable as a list
34+
def ELFStringTable.allStrings (st : ELFStringTable) : List StringTableEntry := Id.run do
35+
let mut idx := 0
36+
let mut idx₂ := 0
37+
let mut rslt := []
38+
for ptr in st.strings do
39+
if ptr = 0 then do
40+
let range := st.strings.extract idx idx₂
41+
let chars := range.toList.map (λbyte => Char.ofNat byte.toNat)
42+
rslt := ⟨String.mk chars, idx⟩::rslt
43+
idx := idx₂ + 1 -- point to the head of the next string, if there is one
44+
idx₂ := idx₂ + 1 -- sync with ptr
45+
return rslt
46+
47+
-- Get the offset associated with a given string inside of a string table
48+
def ELFStringTable.stringToOffset (st : ELFStringTable) (str : String) : Option Nat := do
49+
let strings := st.allStrings
50+
let entry ← strings.find? (·.string = str)
51+
return entry.offset

Main.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def readCmd : Cmd := `[Cli|
6161
c, "archive-index"; "Display the symbol/file index in an archive"
6262
D, "use-dynamic"; "Use the dynamic section info when displaying symbols"
6363
L, "lint"; "Display warning messages for possible problems"
64-
x, "hex-dump" : Nat; "hex-dump=<number|name>. " ++
64+
x, "hex-dump" : String; "hex-dump=<number|name>. " ++
6565
"Dump the contents of section <number|name> as bytes"
6666
p, "string-dump" : Nat; "--string-dump=<number|name>. " ++
6767
"Dump the contents of section <number|name> as strings"

0 commit comments

Comments
 (0)