hare

[hare] The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

abbrev.ha (2505B)


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