abbrev.ha (2524B)
1 // SPDX-License-Identifier: MPL-2.0 2 // (c) Hare authors <https://harelang.org> 3 4 use debug::image; 5 use errors; 6 use format::elf; 7 use io; 8 use memio; 9 use sort; 10 11 export type abbrev_table = struct { 12 items: []abbrev, 13 }; 14 15 // A single abbreviated tag from a .debug_abbrev section. 16 export type abbrev = struct { 17 code: u64, 18 tag: u32, 19 has_children: bool, 20 fields: []afield, 21 }; 22 23 // A field in a .debug_abbrev section 24 export type afield = struct { 25 attr: u32, 26 form: u32, 27 }; 28 29 // Loads an abbreviation table from the .debug_abbrev section, loading the table 30 // at the provided offset from the start of the ELF section. 31 // 32 // Pass the result to [[abbrev_table_finish]] to free resources associated with 33 // the table when you're done with it. 34 export fn load_abbrevs( 35 image: *image::image, 36 offs: u64, 37 ) (abbrev_table | void | errors::invalid) = { 38 const sec = match (image::section_byname(image, ".debug_abbrev")) { 39 case let sec: *elf::section64 => 40 yield sec; 41 case null => 42 return; 43 }; 44 45 const rd = image::section_reader(image, sec); 46 io::seek(&rd, offs: io::off, io::whence::SET)!; 47 const rd = new_table_reader(&rd, false)! as table_reader; 48 49 let abbrevs: []abbrev = []; 50 for (true) { 51 match (read_abbrev(&rd)) { 52 case io::EOF => break; 53 case io::error => return errors::invalid; 54 case let ab: abbrev => 55 append(abbrevs, ab); 56 }; 57 }; 58 59 return abbrev_table { 60 items = abbrevs, 61 }; 62 }; 63 64 // Reads an entry from an abbreviation table. 65 fn read_abbrev( 66 rd: *table_reader, 67 ) (abbrev | io::EOF | io::error) = { 68 const code = read_uleb128(rd)?; 69 if (code == 0) { 70 return io::EOF; 71 }; 72 const tag = read_uleb128(rd)?; 73 const children = read_ubyte(rd)? != 0; 74 75 let fields: []afield = []; 76 for (true) { 77 const name = read_uleb128(rd)?; 78 const form = read_uleb128(rd)?; 79 if (name == 0 && form == 0) { 80 break; 81 }; 82 append(fields, afield { 83 attr = name: u32, 84 form = form: u32, 85 }); 86 }; 87 88 return abbrev { 89 code = code, 90 tag = tag: u32, 91 has_children = children, 92 fields = fields, 93 }; 94 }; 95 96 // Frees resources associated with an [[abbrev_table]]. 97 export fn abbrev_table_finish(table: *abbrev_table) void = { 98 for (let i = 0z; i < len(table.items); i += 1) { 99 free(table.items[i].fields); 100 }; 101 free(table.items); 102 }; 103 104 // Retrieves an abbreviation from an [[abbrev_table]] by its abbreviation code. 105 export fn get_abbrev(table: *abbrev_table, code: u64) const nullable *abbrev = { 106 // TODO: Sort the list and do this faster 107 for (let item &.. table.items) { 108 if (item.code == code) { 109 return item; 110 }; 111 }; 112 return null; 113 };