symbols.ha (2583B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use bytes; 5 use debug::image; 6 use io; 7 use format::elf; 8 use strings; 9 use types::c; 10 11 // Returns symbol information by name. 12 export fn symbol_byname( 13 image: *image::image, 14 name: str, 15 ) (elf::sym64 | io::error | void) = { 16 const strtab = match (image::section_byname(image, ".strtab")) { 17 case let sec: *elf::section64 => 18 yield sec; 19 case null => 20 return; 21 }; 22 const symtab = match (image::section_byname(image, ".symtab")) { 23 case let sec: *elf::section64 => 24 yield sec; 25 case null => 26 return; 27 }; 28 29 const st_name = scan_strtab(image, strtab, name) as u64; 30 const data = image::section_data(image, symtab); 31 const entsz = symtab.sh_entsize: size; 32 const nsym = len(data) / entsz; 33 for (let i = 0z; i < nsym; i += 1) { 34 const sym = &data[i * entsz]: *elf::sym64; 35 if (sym.st_name == st_name) { 36 return *sym; 37 }; 38 }; 39 }; 40 41 // Returns the symbol that occupies a given address. 42 export fn symbol_byaddr( 43 image: *image::image, 44 addr: uintptr, 45 ) (elf::sym64 | io::error | void) = { 46 const addr = addr: u64; 47 const symtab = match (image::section_byname(image, ".symtab")) { 48 case let sec: *elf::section64 => 49 yield sec; 50 case null => 51 return; 52 }; 53 54 const data = image::section_data(image, symtab); 55 const entsz = symtab.sh_entsize: size; 56 const nsym = len(data) / entsz; 57 for (let i = 0z; i < nsym; i += 1) { 58 const sym = &data[i * entsz]: *elf::sym64; 59 const min = sym.st_value; 60 const max = sym.st_value + sym.st_size; 61 if (min <= addr && addr < max) { 62 return *sym; 63 }; 64 }; 65 }; 66 67 // Returns the name of the given symbol, or void if the executable was stripped. 68 export fn symbol_name( 69 image: *image::image, 70 sym: *elf::sym64, 71 ) (const str | io::error | void) = { 72 const strtab = match (image::section_byname(image, ".strtab")) { 73 case let sec: *elf::section64 => 74 yield sec; 75 case null => 76 return; 77 }; 78 const data = image::section_data(image, strtab); 79 return c::tostr(&data[sym.st_name]: *const c::char)!; 80 }; 81 82 // Scans a string table for a given name and returns the index of that name. 83 fn scan_strtab( 84 image: *image::image, 85 strtab: *elf::section64, 86 name: str, 87 ) (u64 | io::error | void) = { 88 let buf: [4096]u8 = [0...]; 89 let namebuf: [MAX_SYMNAME]u8 = [0...]; 90 91 // Prepare a nul-terminated byte slice of the name 92 let name = strings::toutf8(name); 93 namebuf[..len(name)] = name; 94 namebuf[len(name)] = 0; 95 name = namebuf[..len(name)+1]; 96 97 const data = image::section_data(image, strtab); 98 match (bytes::index(data, name)) { 99 case let z: size => 100 return z: u64; 101 case void => void; 102 }; 103 };