sections.ha (2649B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use format::elf; 5 use format::elf::{sht}; 6 use types::c; 7 use memio; 8 9 // Check that this section is actually a reference to this image. 10 fn section_validate(image: *image, sec: *elf::section64) void = { 11 const addr = sec: uintptr; 12 const min = &image.data[0]: uintptr; 13 const max = min + len(image.data): uintptr; 14 assert(min <= addr && max > addr, "section_name: invalid section"); 15 }; 16 17 // Returns a program section by name. Returns null if there is no such section, 18 // or if the section names are not available in this image (e.g. because it was 19 // stripped). 20 export fn section_byname( 21 image: *image, 22 name: str, 23 ) nullable *elf::section64 = { 24 const cached = [ 25 (".symtab", &image.symtab), 26 (".strtab", &image.strtab), 27 (".debug_abbr", &image.debug_abbr), 28 (".debug_aranges", &image.debug_aranges), 29 (".debug_info", &image.debug_info), 30 (".debug_line", &image.debug_line), 31 (".debug_str", &image.debug_str), 32 ]; 33 for (const (cand, val) .. cached) { 34 if (cand == name) { 35 match (*val) { 36 case null => break; 37 case let sec: *elf::section64 => 38 return sec; 39 }; 40 }; 41 }; 42 43 const head = image.header; 44 let r: nullable *elf::section64 = null; 45 for (let i = 0u16; i < head.e_shnum; i += 1) { 46 const shoffs = head.e_shoff + i * head.e_shentsize; 47 const sec = &image.data[shoffs]: *elf::section64; 48 if (sec.sh_type == sht::NULL) { 49 continue; 50 }; 51 52 const cand = section_name(image, sec); 53 if (cand == name) { 54 r = sec; 55 break; 56 }; 57 }; 58 59 match (r) { 60 case null => 61 return null; 62 case let sec: *elf::section64 => 63 for (let (cand, val) .. cached) { 64 if (cand == name) { 65 *val = sec; 66 break; 67 }; 68 }; 69 }; 70 71 return r; 72 }; 73 74 // Returns the name of this [[elf::section64]], returning "" if the section 75 // names are not available in this image (i.e. it has been stripped). 76 export fn section_name( 77 image: *image, 78 sec: *elf::section64, 79 ) const str = { 80 section_validate(image, sec); 81 82 const shtab = match (image.shstrtab) { 83 case let sec: *elf::section64 => 84 yield sec; 85 case null => 86 return ""; 87 }; 88 89 const offs = shtab.sh_offset + sec.sh_name; 90 return c::tostr(&image.data[offs]: *const c::char)!; 91 }; 92 93 // Returns a slice of the data contained with a given section. 94 export fn section_data(image: *image, sec: *elf::section64) []u8 = { 95 section_validate(image, sec); 96 return image.data[sec.sh_offset..sec.sh_offset+sec.sh_size]; 97 }; 98 99 // Returns a [[memio::fixed]] reader for the given section. 100 export fn section_reader(image: *image, sec: *elf::section64) memio::stream = { 101 const data = section_data(image, sec); 102 return memio::fixed(data); 103 };