hare

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

aranges.ha (1689B)


      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 // Supported version of .debug_aranges decoder
     10 def ARANGES_VERSION: u16 = 2;
     11 
     12 // Returns the debug_info offset for the DIE that corresponds to this address,
     13 // if known, or void if unknown.
     14 export fn arange_lookup(
     15 	image: *image::image,
     16 	addr: uintptr,
     17 ) (u64 | void | errors::invalid) = {
     18 	const aranges = match (image::section_byname(image, ".debug_aranges")) {
     19 	case let sec: *elf::section64 =>
     20 		yield sec;
     21 	case null =>
     22 		return;
     23 	};
     24 
     25 	// Read all arange tables in this section
     26 	const rd = image::section_reader(image, aranges);
     27 	for (const rd => new_table_reader(&rd, true)!) {
     28 		match (arange_match(&rd, addr)) {
     29 		case void => void;
     30 		case let u: u64 =>
     31 			return u;
     32 		case io::error =>
     33 			return errors::invalid;
     34 		};
     35 	};
     36 };
     37 
     38 fn arange_match(rd: *table_reader, addr: uintptr) (u64 | void | io::error) = {
     39 	const ver = read_uhalf(rd)?;
     40 	const info_offset = read_secword(rd)?;
     41 	const asize = read_ubyte(rd)?;
     42 	const ssize = read_ubyte(rd)?;
     43 	assert(ver == ARANGES_VERSION, "debug::dwarf: unsupported .debug_ranges version");
     44 	assert(ssize == 0, "debug::dwarf: unsupported segmented target for .debug_aranges");
     45 	assert(asize == 8, "debug::dwarf: unsupported address size for .debug_aranges");
     46 
     47 	read_align(rd, asize * 2)?;
     48 
     49 	const au64 = addr: u64;
     50 	for (!read_iseof(rd)) {
     51 		const min = read_ulong(rd)?;
     52 		const length = read_ulong(rd)?;
     53 		if (min == 0 && length == 0) {
     54 			if (!read_iseof(rd)) {
     55 				return errors::invalid;
     56 			};
     57 			break;
     58 		};
     59 		const max = min + length;
     60 		if (min <= au64 && max > au64) {
     61 			return info_offset;
     62 		};
     63 	};
     64 };