UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
syms_dwarf_parser.c
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#ifndef SYMS_DWARF_PARSER_C
4#define SYMS_DWARF_PARSER_C
5
6// TODO(rjf):
7//
8// [ ] Any time we encode a subrange of a section inside of a
9// SYMS_DwAttribValue, we need to do that consistently, regardless of
10// whether or not it is a string, memory block, etc. We should just use
11// the SYMS_DwSectionKind and then the min/max pair.
12//
13// [ ] Things we are not reporting, or haven't figured out:
14// @dwarf_expr @dwarf_v5 @dw_cross_unit
15// [ ] currently, we're filtering out template arguments in the member accelerator.
16// this is because they don't correspond one-to-one with anything in PDB, but
17// they do contain useful information that we might want to expose another way
18// somehow.
19// [ ] DWARF V5 features that nobody seems to use right now
20// [ ] ref_addr_desc + next_info_ctx
21// apparently these are necessary when dereferencing some DWARF V5 ways of
22// forming references. They don't seem to come up at all for any real data
23// but might be a case somewhere.
24// [ ] case when only .debug_line and .debug_line_str is available, without
25// compilation unit debug info? do we care about this at all?
26// [ ] SYMS_DwFormKind_REF_SIG8, which requires using .debug_names
27// to do a lookup for a reference
28// [ ] DWARF V5, but also V1 & V2 for syms_dw_range_list_from_range_offset
29// [ ] SYMS_DwAttribClass_RNGLIST and SYMS_DwFormKind_RNGLISTX
30// [ ] SYMS_DwOpCode_XDEREF_SIZE + SYMS_DwOpCode_XDEREF
31// [ ] SYMS_DwOpCode_PIECE + SYMS_DwOpCode_BIT_PIECE
32// [ ] SYMS_DwExtOpcode_DEFINE_FILE, for line info
33// [ ] DWARF procedures in DWARF expr evaluation
34// [ ] SYMS_DwAttribKind_DATA_MEMBER_LOCATION is not being *fully* handled right
35// now; full handling requires evaluating a DWARF expression to find out the
36// offset of a member. Right now we handle the common case, which is when it
37// is encoded as a constant value.
38// [ ] inline information
39// [ ] full info we are not handling:
40// [ ] friend classes
41// [ ] DWARF macro info
42// [ ] whether or not a function is the entry point
43// [ ] attributes we are not handling that may be important:
44// [ ] SYMS_DwAttribKind_ABSTRACT_ORIGIN
45// - ???
46// [ ] SYMS_DwAttribKind_VARIABLE_PARAMETER
47// - determines whether or not a parameter to a function is mutable, I think?
48// [ ] SYMS_DwAttribKind_MUTABLE
49// - I think this is for specific keywords, may not be relevant to C/++
50// [ ] SYMS_DwAttribKind_CALL_COLUMN
51// - column position of an inlined subroutine
52// [ ] SYMS_DwAttribKind_CALL_FILE
53// - file of inlined subroutine
54// [ ] SYMS_DwAttribKind_CALL_LINE
55// - line number of inlined subroutine
56// [ ] SYMS_DwAttribKind_CONST_EXPR
57// - ??? maybe C++ constexpr?
58// [ ] SYMS_DwAttribKind_ENUM_CLASS
59// - c++ thing that's an enum with a backing type
60// [ ] SYMS_DwAttribKind_LINKAGE_NAME
61// - name used to do linking
62
64//~ rjf: Globals
65
67
69//~ rjf: Basic Helpers
70
73{
74 SYMS_U64 result = 5381;
75 for(SYMS_U64 i = 0; i < string.size; i += 1)
76 {
77 result = ((result << 5) + result) + string.str[i];
78 }
79 return result;
80}
81
82#if 1
85{
86 SYMS_U64 low_bit = id & 1;
87 SYMS_U64 chaotic_bits = id & 0x0000000000000007;
88 SYMS_U64 hash = (id >> 3) | (chaotic_bits << 61);
89 for(SYMS_U64 rot = 0; rot < chaotic_bits; rot += 1)
90 {
91 SYMS_U64 lower_portion = hash & 0x1FFFFFFFFFFFFFFF;
94 hash = (hash & 0xE000000000000000) | lower_portion_rotated;
95 }
96 hash = ((hash & 0xE000000000000000) >> 61) | ((hash & 0x1FFFFFFFFFFFFFFF) << 3);
97 hash |= low_bit;
98 return hash;
99}
100#elif 0
103{
104 SYMS_U64 low_bit = id & 1;
105 SYMS_U64 h = (id >> 4) << 1;
106 h &= 0xfffffffffffffffe;
107 h += low_bit;
108 return h;
109}
110#elif 0
113{
114 SYMS_U64 x = id;
115 SYMS_U64 z = (x += 0x9e3779b97f4a7c15);
116 z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
117 z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
118 return z ^ (z >> 31);
119}
120#else
123{
124 SYMS_U64 key = id;
125 key = ~key + (key << 21);
126 key = (key << 21) - key - 1;
127 key = key ^ (key >> 24);
128 key = (key + (key << 3)) + (key << 8);
129 key = key ^ (key >> 14);
130 key = (key + (key << 2)) + (key << 4);
131 key = key ^ (key >> 28);
132 key = key + (key << 31);
133 return key;
134}
135#endif
136
142
145{
146 // NOTE(rjf): DWARF's spec specifies two mappings:
147 // (SYMS_DwAttribKind) => List(SYMS_DwAttribClass)
148 // (SYMS_DwFormKind) => List(SYMS_DwAttribClass)
149 //
150 // This function's purpose is to find the overlapping class between an
151 // SYMS_DwAttribKind and SYMS_DwFormKind.
152 SYMS_DwAttribClass result = 0;
155
156 switch(ver)
157 {
158 case SYMS_DwVersion_V1: break;
160 {
163
164 // rust compiler writes version 5 attributes
165 if(lang == SYMS_DwLanguage_Rust && (attrib_info == 0 || form_info == 0))
166 {
169 }
170 } break;
174 {
177 } break;
178 }
179
180 if(attrib_info != 0 && form_info != 0)
181 {
183 for(SYMS_U32 i = 0; i < 32; ++i)
184 {
185 SYMS_U32 n = 1u << i;
186 if((attrib_info & n) != 0 && (form_info & n) != 0)
187 {
188 result = ((SYMS_DwAttribClass) n);
189 break;
190 }
191 }
192 }
193
194 return result;
195}
196
199{
201 switch(stub->kind)
202 {
203 //- rjf: procs
206 {
208 }break;
209
210 //- rjf: constants
212 {
214 }break;
215
216 //- rjf: types
234
235 //- rjf: variables
238
239 //- rjf: variables that could possibly be static
242 {
248 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, resolve_params.language, resolve_params.version, resolve_params.addr_size, stub);
249 for(SYMS_DwAttribNode *attrib_n = attribs.first;
250 attrib_n != 0;
251 attrib_n = attrib_n->next)
252 {
253 SYMS_DwAttrib *attrib = &attrib_n->attrib;
255 {
257 }
258 else if(attrib->attrib_kind == SYMS_DwAttribKind_LOCATION)
259 {
261 location_value = syms_dw_attrib_value_from_form_value(data, dbg, resolve_params,
262 attrib->form_kind,
263 attrib->value_class,
264 attrib->form_value);
265 }
267 {
269 }
270 }
271
273 if(has_location)
274 {
277 location_value.v[0] + location_value.v[1]);
278
279 // TODO(allen): fill this in correctly
283 }
284
285 if(has_const_val)
286 {
288 }
290 {
292 }
294 {
296 }
298 }break;
299
300 //- rjf: scopes
303
304 default: break;
305 }
306 return symbol_kind;
307}
308
311{
312 SYMS_SecInfoArray result = {0};
313 result.count = array.count;
314 result.sec_info = syms_push_array_zero(arena, SYMS_SecInfo, result.count);
315 for(SYMS_U64 idx = 0; idx < array.count; idx += 1)
316 {
317 result.sec_info[idx].vrange = array.sec_info[idx].vrange;
318 result.sec_info[idx].frange = array.sec_info[idx].frange;
319 result.sec_info[idx].name = syms_push_string_copy(arena, array.sec_info[idx].name);
320 }
321 return result;
322}
323
326{
329 SYMS_U8 slash_char = '/';
330
331 //- rjf: get pieces of full path from dir
333 {
334 SYMS_U64 start = 0;
335 for(SYMS_U64 idx = 0; idx <= dir.size; idx += 1)
336 {
337 if(idx == dir.size && idx > start)
338 {
339 SYMS_String8 str = syms_str8(dir.str+start, idx-start);
341 }
342 else if(idx < dir.size && (dir.str[idx] == '/' || dir.str[idx] == '\\'))
343 {
344 if(idx == 0)
345 {
347 }
348 if(dir.str[idx] == '\\')
349 {
350 slash_char = '\\';
351 }
352 if(idx - start != 0)
353 {
354 SYMS_String8 str = syms_str8(dir.str+start, idx-start);
356 }
357 start = idx+1;
358 }
359 }
360 }
361
362 //- rjf: get pieces of full path from filename
363 {
364 SYMS_U64 start = 0;
365 for(SYMS_U64 idx = 0; idx <= filename.size; idx += 1)
366 {
367 if(idx == filename.size && idx > start)
368 {
369 SYMS_String8 str = syms_str8(filename.str+start, idx-start);
371 }
372 else if(idx < filename.size && (filename.str[idx] == '/' || filename.str[idx] == '\\'))
373 {
374 if(idx - start != 0)
375 {
376 SYMS_String8 str = syms_str8(filename.str+start, idx-start);
378 }
379 start = idx+1;
380 }
381 }
382 }
383
384 SYMS_String8 result = {0};
385 SYMS_StringJoin join = {0};
387 join.sep = syms_str8(&slash_char, 1);
388 result = syms_string_list_join(arena, &pieces, &join);
390 return result;
391}
392
393SYMS_API void
395{
397 if(chunk == 0 || chunk->count >= SYMS_ARRAY_SIZE(chunk->ids))
398 {
400 SYMS_QueuePush(list->first, list->last, chunk);
401 list->chunk_count += 1;
402 }
403 chunk->ids[chunk->count] = sid;
404 chunk->count += 1;
405 list->total_id_count += 1;
406}
407
410{
412 array.count = list.total_id_count;
413 array.ids = syms_push_array(arena, SYMS_SymbolID, array.count);
414 SYMS_U64 idx = 0;
415 for(SYMS_DwSymbolIDChunk *chunk = list.first; chunk != 0; chunk = chunk->next)
416 {
417 syms_memmove(array.ids + idx, chunk->ids, chunk->count*sizeof(SYMS_SymbolID));
418 idx += chunk->count;
419 }
420 return array;
421}
422
424//~ rjf: DWARF-Specific Based Range Reads
425
428{
430 SYMS_U64 value = 0;
431 SYMS_U32 first32 = 0;
432 if(syms_based_range_read_struct(base, range, offset, &first32))
433 {
434 // NOTE(rjf): DWARF 32-bit => use the first 32 bits as the size.
435 if(first32 != 0xffffffff)
436 {
437 value = (SYMS_U64)first32;
438 bytes_read = sizeof(SYMS_U32);
439 }
440 // NOTE(rjf): DWARF 64-bit => first 32 are just a marker, use the next 64 bits as the size.
441 else if(syms_based_range_read_struct(base, range, offset + sizeof(SYMS_U32), &value))
442 {
443 value = 0;
444 bytes_read = sizeof(SYMS_U32) + sizeof(SYMS_U64);
445 }
446 }
447 if(out_value != 0)
448 {
449 *out_value = value;
450 }
451 return bytes_read;
452}
453
456{
458
459 //- rjf: parse ID
460 SYMS_U64 id_off = offset;
462 SYMS_U64 id = 0;
463 {
467 }
468
469 //- rjf: parse sub-kind
470 SYMS_U64 sub_kind = 0;
471 SYMS_U64 next_off = sub_kind_off;
472 if(id != 0)
473 {
475 next_off += bytes_read;
477 }
478
479 //- rjf: parse whether this tag has children
480 SYMS_U8 has_children = 0;
481 if(id != 0)
482 {
483 total_bytes_read += syms_based_range_read_struct(base, range, next_off, &has_children);
484 }
485
486 //- rjf: fill abbrev
487 if(out_abbrev != 0)
488 {
492 abbrev.abbrev_range = syms_make_u64_range(range.min+offset, range.min+offset+total_bytes_read);
493 abbrev.sub_kind = sub_kind;
494 abbrev.id = id;
495 if(has_children)
496 {
498 }
500 }
501
502 return total_bytes_read;
503}
504
507{
509
510 //- rjf: parse ID
511 SYMS_U64 id_off = offset;
513 SYMS_U64 id = 0;
514 {
518 }
519
520 //- rjf: parse sub-kind (form-kind)
521 SYMS_U64 sub_kind = 0;
522 SYMS_U64 next_off = sub_kind_off;
523 {
525 next_off += bytes_read;
527 }
528
529 //- rjf: parse implicit const
531 if(sub_kind == SYMS_DwFormKind_IMPLICIT_CONST)
532 {
535 }
536
537 //- rjf: fill abbrev
538 if(out_abbrev != 0)
539 {
543 abbrev.abbrev_range = syms_make_u64_range(offset, offset+total_bytes_read);
544 abbrev.sub_kind = sub_kind;
545 abbrev.id = id;
546 if(sub_kind == SYMS_DwFormKind_IMPLICIT_CONST)
547 {
549 abbrev.const_value = implicit_const;
550 }
552 }
553
554 return total_bytes_read;
555}
556
559{
562 SYMS_DwAttribValue form_value;
563 syms_memzero_struct(&form_value);
564
565 switch(form_kind)
566 {
567
568 //- rjf: 1-byte uint reads
572
573 //- rjf: 2-byte uint reads
577
578 //- rjf: 3-byte uint reads
581
582 //- rjf: 4-byte uint reads
585
586 //- rjf: 8-byte uint reads
589
590 //- rjf: address-size reads
591 case SYMS_DwFormKind_ADDR: bytes_to_read = address_size; goto read_fixed_uint;
592
593 //- rjf: offset-size reads
597
598 //- rjf: fixed-size uint reads
599 {
601 SYMS_U64 value = 0;
602 bytes_read = syms_based_range_read(base, range, offset, bytes_to_read, &value);
603 form_value.v[0] = value;
604 }break;
605
606 //- rjf: uleb128 reads
609 {
610 SYMS_U64 value = 0;
611 bytes_read = syms_based_range_read_uleb128(base, range, offset, &value);
612 form_value.v[0] = value;
613 }break;
614
615 //- rjf: sleb128 reads
617 {
618 SYMS_S64 value = 0;
619 bytes_read = syms_based_range_read_sleb128(base, range, offset, &value);
620 form_value.v[0] = value;
621 }break;
622
623 //- rjf: fixed-size uint read + skip
627 {
629 SYMS_U64 size = 0;
630 bytes_read = syms_based_range_read(base, range, offset, bytes_to_read, &size);
631 form_value.v[0] = size;
632 form_value.v[1] = offset;
633 bytes_read += size;
634 }break;
635
636 //- rjf: uleb 128 read + skip
638 {
639 SYMS_U64 size = 0;
640 bytes_read = syms_based_range_read_uleb128(base, range, offset, &size);
641 form_value.v[0] = size;
642 form_value.v[1] = offset;
643 bytes_read += size;
644 }break;
645
646 //- rjf: u64 ranges
648 {
649 SYMS_U64 value1 = 0;
650 SYMS_U64 value2 = 0;
651 bytes_read += syms_based_range_read_struct(base, range, offset, &value1);
652 bytes_read += syms_based_range_read_struct(base, range, offset + sizeof(SYMS_U64), &value2);
653 form_value.v[0] = value1;
654 form_value.v[1] = value2;
655 }break;
656
657 //- rjf: strings
659 {
660 SYMS_String8 string = syms_based_range_read_string(base, range, offset);
661 bytes_read = string.size + 1;
662 SYMS_U64 string_offset = offset;
664 form_value.v[0] = string_offset;
665 form_value.v[1] = string_offset+string_size-1;
666 }break;
667
668 //- rjf: implicit const
670 {
671 // NOTE(nick): This is special case.
672 // Unlike other forms that have their values stored in the .debug_info section,
673 // This one defines it's value in the .debug_abbrev section.
674 form_value.v[0] = implicit_const;
675 }break;
676
677 //- rjf: expr loc
679 {
680 SYMS_U64 size = 0;
681 bytes_read = syms_based_range_read_uleb128(base, range, offset, &size);
682 form_value.v[0] = offset + bytes_read;
683 form_value.v[1] = size;
684 bytes_read += size;
685 }break;
686
687 //- rjf: flag present
689 {
690 form_value.v[0] = 1;
691 }break;
692
694 {
696 }break;
697
699 {
700 }break;
701 }
702
703 if(form_value_out != 0)
704 {
705 *form_value_out = form_value;
706 }
707
708 return bytes_read;
709}
710
712//~ rjf: Debug Info Accelerator (DbgAccel) code
713
714//- rjf: debug info and interaction with ELF file accel
715
718{
719 SYMS_B32 result = syms_false;
721 {
722 syms_str8_comp(".debug_info"),
723 };
727 {
729 for(SYMS_U64 section_idx = 0;
730 section_idx < bin_accel->sections.count;
731 section_idx += 1)
732 {
734 {
736 break;
737 }
738 }
739 if(found)
740 {
741 result = syms_true;
742 }
743 else
744 {
745 result = syms_false;
746 break;
747 }
748 }
749 return result;
750}
751
754{
758 for(SYMS_U64 i = 0; i < sec_array.count; i += 1)
759 {
760 if(syms_string_match(sec_array.sec_info[i].name, syms_str8_lit("__debug_info"), 0) ||
761 syms_string_match(sec_array.sec_info[i].name, syms_str8_lit("__debug_line"), 0))
762 {
764 break;
765 }
766 }
768 return is_dbg;
769}
770
773{
774 //- rjf: scan file accel for info and abbrev sections, which are all that is necessary for
775 // some useful debug info to come from DWARF.
777 {
779 {
782 };
785 {
789 for(SYMS_U64 section_idx = 0; section_idx < sections.count; section_idx += 1)
790 {
794 {
795 match_count += 1;
796 break;
797 }
798 }
799 }
801 }
802
803 //- rjf: scan sections for .text section, so we can store its index (useful for
804 // later stuff in the expression transpiler)
805 SYMS_U64 text_section_idx = 0;
806 for(SYMS_U64 idx = 0; idx < sections.count; idx += 1)
807 {
808 if(syms_string_match(sections.sec_info[idx].name, syms_str8_lit(".text"), 0))
809 {
810 text_section_idx = idx;
811 break;
812 }
813 }
814
815 //- rjf: build section map
816 SYMS_DwSection *section_map = 0;
817 SYMS_B32 is_dwo = syms_false;
819 {
824 {
828 for(SYMS_U64 section_idx = 0; section_idx < sections.count; section_idx += 1)
829 {
834 {
835 section_map[section_kind].range = sections.sec_info[section_idx].frange;
837 {
838 is_dwo = syms_true;
839 }
840 break;
841 }
842 }
843 }
844 }
845
846 //- rjf: find acceptable vrange for this file, to detect busted line info sections later
847 SYMS_U64Range acceptable_vrange = {0};
849 {
850 for(SYMS_U64 idx = 0; idx < sections.count; idx += 1)
851 {
852 acceptable_vrange.min = SYMS_MIN(acceptable_vrange.min, sections.sec_info[idx].vrange.min);
853 acceptable_vrange.max = SYMS_MAX(acceptable_vrange.max, sections.sec_info[idx].vrange.max);
854 }
855 }
856
857 //- rjf: find .debug_info and .debug_aranges for initial quick parse
858 void *info_base = 0;
861 void *aranges_base = 0;
864 {
865 info_base = data.str + section_map[SYMS_DwSectionKind_Info].range.min;
870 }
871
872 //- rjf: parse comp unit range info from .debug_info and .debug_aranges
873 SYMS_U64 unit_count = 0;
874 SYMS_DwUnitRangeInfo *unit_range_info = 0;
876 {
878
879 //- rjf: get all comp unit file ranges
881 {
882 for(SYMS_U64 offset = 0;;)
883 {
886 if(info_size == 0)
887 {
888 break;
889 }
891 SYMS_U64 info_start = info_rng.min + offset;
894 offset += total_info_size;
895 }
896 }
897 unit_count = unit_franges.node_count;
898
899 //- rjf: get all comp unit addr ranges via .debug_aranges
901 {
902 for(SYMS_U64 offset = 0; offset < aranges_rng.max;)
903 {
904 // rjf: parse hdr
905 SYMS_U64 unit_length = 0;
906 SYMS_U16 version = 0;
908 SYMS_U8 address_size = 0;
910 offset += syms_dw_based_range_read_length(aranges_base, aranges_rng, offset, &unit_length);
911 offset += syms_based_range_read_struct(aranges_base, aranges_rng, offset, &version);
913 offset += syms_based_range_read_struct(aranges_base, aranges_rng, offset, &address_size);
915
916 // rjf: figure out which UID we're looking at
917 SYMS_UnitID uid = 0;
918 SYMS_U64 unit_idx = 0;
919 {
920 for(SYMS_U64RangeNode *n = unit_franges.first; n != 0; n = n->next, unit_idx += 1)
921 {
922 if(n->range.min <= debug_info_offset && debug_info_offset < n->range.max)
923 {
924 uid = unit_idx+1;
925 break;
926 }
927 }
928 }
929
930 // rjf: figure out tuple size
931 SYMS_U64 tuple_size = address_size*2 + segment_size;
932
933 // rjf: adjust parsing offset to be divisible by the tuple size (see the February 13, 2017 spec)
936 {
938 }
939
940 // rjf: parse tuples
942 {
943 for(;;)
944 {
945 SYMS_U64 segment = 0;
946 SYMS_U64 address = 0;
947 SYMS_U64 length = 0;
948 offset += syms_based_range_read(aranges_base, aranges_rng, offset, segment_size, &segment);
949 offset += syms_based_range_read(aranges_base, aranges_rng, offset, address_size, &address);
950 offset += syms_based_range_read(aranges_base, aranges_rng, offset, address_size, &length);
951 if(segment == 0 && address == 0 && length == 0)
952 {
953 break;
954 }
955 if(length != 0 && acceptable_vrange.min <= address && address < acceptable_vrange.max)
956 {
957 SYMS_U64Range rng = syms_make_u64_range(address, address+length);
959 }
960 }
961 }
962
963 // rjf: fill unit_aranges slot
965
966 // rjf: log
967#if SYMS_ENABLE_DEV_LOG
969 {
970 SYMS_Log(".debug_aranges [unit #%i]:\n", uid);
971 for(SYMS_U64 idx = 0; idx < unit_aranges[unit_idx].count; idx += 1)
972 {
973 SYMS_Log(" [0x%" SYMS_PRIx64 ", 0x%" SYMS_PRIx64 ")\n", unit_aranges[unit_idx].ranges[idx].min, unit_aranges[unit_idx].ranges[idx].max);
974 }
975 }
977#endif
978 }
979 }
980
981 //- rjf: build range info array
982 unit_range_info = syms_push_array_zero(arena, SYMS_DwUnitRangeInfo, unit_franges.node_count);
983 {
985 for(SYMS_U64 unit_idx = 0;
986 unit_idx < unit_franges.node_count && frange_node != 0;
987 unit_idx += 1, frange_node = frange_node->next)
988 {
989 unit_range_info[unit_idx].uid = unit_idx+1;
990 unit_range_info[unit_idx].frange = frange_node->range;
991 unit_range_info[unit_idx].addr_ranges = unit_aranges[unit_idx];
992 }
993 }
994
996 }
997
998 //- rjf: fill+return
1001 {
1002 dbg = syms_push_array_zero(arena, SYMS_DwDbgAccel, 1);
1004 dbg->arch = arch;
1005 dbg->vbase = vbase;
1006 dbg->sections = syms_dw_copy_sec_info_array(arena, sections);
1007 dbg->text_section_idx = text_section_idx;
1008 dbg->acceptable_vrange = acceptable_vrange;
1009 dbg->section_map = section_map;
1010 dbg->unit_count = unit_count;
1011 dbg->unit_range_info = unit_range_info;
1012 dbg->is_dwo = is_dwo;
1013 }
1014 return dbg;
1015}
1016
1026
1036
1039{
1043 SYMS_DwUnitSetAccel *unit_set = syms_dw_unit_set_accel_from_dbg(scratch.arena, data, dbg);
1045 for(SYMS_U64 unit_num = 1; unit_num <= count; unit_num += 1)
1046 {
1048 SYMS_DwCompRoot *root = syms_dw_comp_root_from_uid(unit_set, uid);
1050 if(ext_ref.dwo_path.size != 0)
1051 {
1053 node->ext_file.file_name = syms_push_string_copy(arena, ext_ref.dwo_path);
1055 syms_memmove(node->ext_file.match_key.v, &ext_ref.dwo_id, sizeof(SYMS_U64));
1056 SYMS_QueuePush(list.first, list.last, node);
1057 list.node_count += 1;
1058 }
1059 }
1061 return list;
1062}
1063
1066{
1068 return result;
1069}
1070
1073{
1074 SYMS_ExtMatchKey key;
1075 syms_memzero_struct(&key);
1076 if(dbg->is_dwo)
1077 {
1080 if(ext_files.node_count != 0)
1081 {
1082 SYMS_ExtFileNode *n = ext_files.first;
1083 key = n->ext_file.match_key;;
1084 }
1086 }
1087 else
1088 {
1089 SYMS_U32 checksum = syms_elf_gnu_debuglink_crc32(0, data);
1090 syms_memmove(key.v, &checksum, sizeof(checksum));
1091 }
1092 return key;
1093}
1094
1097{
1098 return dbg->vbase;
1099}
1100
1101//- rjf: top-level unit info
1102
1105{
1106 SYMS_UnitID uid = 0;
1107 for(SYMS_U64 unit_idx = 0; unit_idx < dbg->unit_count; unit_idx += 1)
1108 {
1109 if(dbg->unit_range_info[unit_idx].frange.min <= foff && foff < dbg->unit_range_info[unit_idx].frange.max)
1110 {
1111 uid = unit_idx+1;
1112 break;
1113 }
1114 }
1115 return uid;
1116}
1117
1118//- rjf: important DWARF section base/range accessors
1119
1122{
1123 SYMS_U64Range range = section_map[kind].range;
1124 SYMS_U64 size = range.max - range.min;
1125 if(size > 0xffffffff)
1126 {
1127 return SYMS_DwMode_64Bit;
1128 }
1129 else
1130 {
1131 return SYMS_DwMode_32Bit;
1132 }
1133}
1134
1137{
1138 SYMS_U64Range *range = &dbg->section_map[kind].range;
1139 SYMS_B32 result = (range->max > range->min);
1140 return(result);
1141}
1142
1143SYMS_API void *
1145{
1146 return data.str + dbg->section_map[kind].range.min;
1147}
1148
1154
1156//~ rjf: Abbrev Table
1157
1160{
1163
1164 SYMS_DwAbbrevTable table;
1165 syms_memzero_struct(&table);
1166
1167 //- rjf: count the tags we have
1168 SYMS_U64 tag_count = 0;
1169 for(SYMS_U64 abbrev_read_off = abbrev_offset - abbrev_range.min;;)
1170 {
1171 SYMS_DwAbbrev tag;
1172 {
1175 if(bytes_read == 0 || tag.id == 0)
1176 {
1177 break;
1178 }
1179 }
1180 for(;;)
1181 {
1182 SYMS_DwAbbrev attrib;
1183 syms_memzero_struct(&attrib);
1186 if(bytes_read == 0 || attrib.id == 0)
1187 {
1188 break;
1189 }
1190 }
1191 tag_count += 1;
1192 }
1193
1194 //- rjf: build table
1195 table.count = tag_count;
1197 syms_memset(table.entries, 0, sizeof(SYMS_DwAbbrevTableEntry)*table.count);
1198 SYMS_U64 tag_idx = 0;
1199 for(SYMS_U64 abbrev_read_off = abbrev_offset - abbrev_range.min;;)
1200 {
1201 SYMS_DwAbbrev tag;
1202 {
1205 if(bytes_read == 0 || tag.id == 0)
1206 {
1207 break;
1208 }
1209 }
1210
1211 // rjf: insert this tag into the table
1212 {
1213 table.entries[tag_idx].id = tag.id;
1214 table.entries[tag_idx].off = tag.abbrev_range.min;
1215 tag_idx += 1;
1216 }
1217
1218 for(;;)
1219 {
1220 SYMS_DwAbbrev attrib;
1221 syms_memzero_struct(&attrib);
1224 if(bytes_read == 0 || attrib.id == 0)
1225 {
1226 break;
1227 }
1228 }
1229 tag_count += 1;
1230 }
1231
1232 return table;
1233}
1234
1237{
1239 if(table.count > 0)
1240 {
1241 SYMS_S64 min = 0;
1242 SYMS_S64 max = (SYMS_S64)table.count - 1;
1243 while(min <= max)
1244 {
1245 SYMS_S64 mid = (min + max) / 2;
1246 if (abbrev_id > table.entries[mid].id)
1247 {
1248 min = mid + 1;
1249 }
1250 else if (abbrev_id < table.entries[mid].id)
1251 {
1252 max = mid - 1;
1253 }
1254 else
1255 {
1256 abbrev_offset = table.entries[mid].off;
1257 break;
1258 }
1259 }
1260 }
1261 return abbrev_offset;
1262}
1263
1265//~ rjf: Miscellaneous DWARF Section Parsing
1266
1267//- rjf: .debug_ranges (DWARF V4)
1268
1271{
1274
1277
1278 SYMS_U64 read_off = range_off;
1279 SYMS_U64 base_addr = comp_unit_base_addr;
1280
1281 for(;read_off < rng.max;)
1282 {
1283 SYMS_U64 v0 = 0;
1284 SYMS_U64 v1 = 0;
1285 read_off += syms_based_range_read(base, rng, read_off, addr_size, &v0);
1286 read_off += syms_based_range_read(base, rng, read_off, addr_size, &v1);
1287
1288 //- rjf: base address entry
1289 if((addr_size == 4 && v0 == 0xffffffff) ||
1290 (addr_size == 8 && v0 == 0xffffffffffffffff))
1291 {
1292 base_addr = v1;
1293 }
1294 //- rjf: end-of-list entry
1295 else if(v0 == 0 && v1 == 0)
1296 {
1297 break;
1298 }
1299 //- rjf: range list entry
1300 else
1301 {
1302 SYMS_U64 min_addr = v0 + base_addr;
1303 SYMS_U64 max_addr = v1 + base_addr;
1305 }
1306 }
1307
1308 return list;
1309}
1310
1311//- rjf: .debug_loc (DWARF V4)
1312
1315{
1316 void *base = syms_dw_sec_base_from_dbg(data, dbg, SYMS_DwSectionKind_Loc);
1318
1319 SYMS_LocRangeList list = {0};
1320
1321 SYMS_U64 read_off = offset;
1322 SYMS_U64 base_addr = comp_unit_base_addr;
1323
1324 for(;read_off < rng.max;)
1325 {
1326 SYMS_U64 v0 = 0;
1327 SYMS_U64 v1 = 0;
1328 read_off += syms_based_range_read(base, rng, read_off, addr_size, &v0);
1329 read_off += syms_based_range_read(base, rng, read_off, addr_size, &v1);
1330
1331 //- rjf: base address entry
1332 if((addr_size == 4 && v0 == 0xffffffff) ||
1333 (addr_size == 8 && v0 == 0xffffffffffffffff))
1334 {
1335 base_addr = v1;
1336 }
1337 //- rjf: end-of-list entry
1338 else if(v0 == 0 && v1 == 0)
1339 {
1340 break;
1341 }
1342 //- rjf: location list entry
1343 else
1344 {
1345 SYMS_U64 start_addr = v0 + base_addr;
1346 SYMS_U64 end_addr = v1 + base_addr;
1347
1348 // rjf: push to list
1352 SYMS_QueuePush(list.first, list.last, n);
1353 list.count += 1;
1354
1355 // rjf: skip past location description
1359 }
1360 }
1361
1362 return list;
1363}
1364
1367{
1368 SYMS_Location result = {0};
1369
1370 void *base = syms_dw_sec_base_from_dbg(data, dbg, SYMS_DwSectionKind_Loc);
1373 SYMS_U16 length = 0;
1378
1379 // TODO(rjf): wire up `location` to `result`, once SYMS_Location changes to
1380 // returning a SYMS_String8 instead of an op list.
1381
1382 return result;
1383}
1384
1385//- rjf: .debug_pubtypes + .debug_pubnames (DWARF V4)
1386
1389{
1392
1394
1395 // TODO(rjf): Arbitrary choice.
1396 names_table.size = 16384;
1398
1400 void *base = syms_dw_sec_base_from_dbg(data, dbg, section_kind);
1402 SYMS_U64 read_off = 0;
1403
1405
1410 SYMS_U64 cu_num = 0;
1416
1417 for(;;)
1418 {
1419 SYMS_U64 info_off = 0;
1420 {
1423 if(bytes_read == 0)
1424 {
1425 break;
1426 }
1427 }
1428
1429 //- rjf: if we got a nonzero .debug_info offset, we've found a valid entry.
1430 if(info_off != 0)
1431 {
1433 read_off += string.size + 1;
1434 SYMS_U64 hash = syms_dw_hash_from_string(string);
1435 SYMS_U64 bucket_idx = hash % names_table.size;
1437 bucket->next = names_table.buckets[bucket_idx];
1438 bucket->string = string;
1439 bucket->sid = syms_dw_sid_from_info_offset(info_off);
1440 bucket->uid = cu_num;
1441 names_table.buckets[bucket_idx] = bucket;
1442 }
1443
1444 //- rjf: if we did not read a proper entry in the table, we need to try to
1445 // read the header of the next table.
1446 else
1447 {
1449 {
1451 if(bytes_read == 0 || next_table_length == 0)
1452 {
1453 break;
1454 }
1456 }
1461 }
1462 }
1463
1465
1466 return names_table;
1467}
1468
1471{
1472 SYMS_USIDList list = {0};
1473 SYMS_U64 hash = syms_dw_hash_from_string(string);
1474 SYMS_U64 idx = hash % tbl.size;
1475 for(SYMS_DwPubStringsBucket *bucket = tbl.buckets[idx]; bucket; bucket = bucket->next)
1476 {
1477 if(syms_string_match(bucket->string, string, 0))
1478 {
1480 n->usid.uid = bucket->uid;
1481 n->usid.sid = bucket->sid;
1482 SYMS_QueuePush(list.first, list.last, n);
1483 list.count += 1;
1484 }
1485 }
1486 return list;
1487}
1488
1489//- rjf: .debug_str_offsets (DWARF V5)
1490
1493{
1494 SYMS_U64 result = 0;
1495
1496 SYMS_DwMode mode = syms_dw_mode_from_sec(dbg->section_map, section);
1497 void *sec_base = syms_dw_sec_base_from_dbg(data, dbg, section);
1499 SYMS_U64 read_off = base;
1500
1501 //- rjf: get the length of each entry
1502 SYMS_U64 entry_len = mode == SYMS_DwMode_64Bit ? 8 : 4;
1503
1504 //- rjf: parse the unit's length (not including the length itself)
1505 SYMS_U64 unit_length = 0;
1506 read_off += syms_dw_based_range_read_length(sec_base, rng, read_off, &unit_length);
1507
1508 //- rjf: parse version
1509 SYMS_U16 version = 0;
1510 read_off += syms_based_range_read_struct(sec_base, rng, read_off, &version);
1511 SYMS_ASSERT_PARANOID(version == 5); // must be 5 as of V5.
1512
1513 //- rjf: parse padding
1514 SYMS_U16 padding = 0;
1515 read_off += syms_based_range_read_struct(sec_base, rng, read_off, &padding);
1516 SYMS_ASSERT_PARANOID(padding == 0); // must be 0 as of V5.
1517
1518 //- rjf: read
1519 if (unit_length >= sizeof(SYMS_U16)*2)
1520 {
1521 void *entries = (SYMS_U8 *)sec_base + read_off;
1522 SYMS_U64 count = (unit_length - sizeof(SYMS_U16)*2) / entry_len;
1523 if(0 <= index && index < count)
1524 {
1525 switch(entry_len)
1526 {
1527 default: break;
1528 case 4: {result = ((SYMS_U32 *)entries)[index];}break;
1529 case 8: {result = ((SYMS_U64 *)entries)[index];}break;
1530 }
1531 }
1532 }
1533
1534 return result;
1535}
1536
1537//- rjf: .debug_addr parsing
1538
1541{
1542 SYMS_U64 result = 0;
1543
1544 void *sec_base = syms_dw_sec_base_from_dbg(data, dbg, section);
1546 SYMS_U64 read_off = base;
1547
1548 //- rjf: parse the unit's length (not including the length itself)
1549 SYMS_U64 unit_length = 0;
1550 read_off += syms_dw_based_range_read_length(sec_base, rng, read_off, &unit_length);
1551
1552 //- rjf: parse version
1553 SYMS_U16 version = 0;
1554 read_off += syms_based_range_read_struct(sec_base, rng, read_off, &version);
1555 SYMS_ASSERT_PARANOID(version == 5); // must be 5 as of V5.
1556
1557 //- rjf: parse address size
1558 SYMS_U8 address_size = 0;
1559 read_off += syms_based_range_read_struct(sec_base, rng, read_off, &address_size);
1560
1561 //- rjf: parse segment selector size
1562 SYMS_U8 segment_selector_size = 0;
1563 read_off += syms_based_range_read_struct(sec_base, rng, read_off, &segment_selector_size);
1564
1565 //- rjf: read
1566 SYMS_U64 entry_size = address_size + segment_selector_size;
1567 SYMS_U64 count = (unit_length - sizeof(SYMS_U16)*2) / entry_size;
1568 if(0 <= index && index < count)
1569 {
1570 void *entry = (SYMS_U8 *)syms_based_range_ptr(sec_base, rng, read_off) + entry_size*index;
1572 SYMS_U64 segment = 0;
1573 SYMS_U64 addr = 0;
1574 syms_based_range_read(entry, entry_rng, 0, sizeof(segment), &segment);
1575 syms_based_range_read(entry, entry_rng, segment_selector_size, sizeof(addr), &addr);
1576 result = addr;
1577 }
1578
1579 return result;
1580}
1581
1582//- rjf: .debug_rnglists + .debug_loclists parsing
1583
1586{
1587 //
1588 // NOTE(rjf): This is only appropriate to call when SYMS_DwFormKind_RNGLISTX is
1589 // used to access a range list, *OR* when SYMS_DwFormKind_LOCLISTX is used to
1590 // access a location list. Otherwise, SYMS_DwFormKind_SEC_OFFSET is required.
1591 //
1592 // See the DWARF V5 spec (February 13, 2017), page 242. (rnglists)
1593 // See the DWARF V5 spec (February 13, 2017), page 215. (loclists)
1594 //
1595
1596 SYMS_U64 result = 0;
1598 void *sec_base = syms_dw_sec_base_from_dbg(data, dbg, section_kind);
1600 SYMS_U64 read_off = base;
1601
1602 //- rjf: get the length of each entry
1603 SYMS_U64 entry_len = mode == SYMS_DwMode_64Bit ? 8 : 4;
1604
1605 //- rjf: parse the unit's length (not including the length itself)
1606 SYMS_U64 unit_length = 0;
1607 read_off += syms_dw_based_range_read_length(sec_base, rng, read_off, &unit_length);
1608
1609 //- rjf: parse version
1610 SYMS_U16 version = 0;
1611 read_off += syms_based_range_read_struct(sec_base, rng, read_off, &version);
1612 SYMS_ASSERT_PARANOID(version == 5); // must be 5 as of V5.
1613
1614 //- rjf: parse address size
1615 SYMS_U8 address_size = 0;
1616 read_off += syms_based_range_read_struct(sec_base, rng, read_off, &address_size);
1617
1618 //- rjf: parse segment selector size
1619 SYMS_U8 segment_selector_size = 0;
1620 read_off += syms_based_range_read_struct(sec_base, rng, read_off, &segment_selector_size);
1621
1622 //- rjf: parse offset entry count
1625
1626 //- rjf: read from offsets array
1628 void *offsets_arr = syms_based_range_ptr(sec_base, rng, read_off);
1629 if(0 <= index && index < (SYMS_U64)offset_entry_count)
1630 {
1632 switch(entry_len)
1633 {
1634 default: break;
1635 case 4: rnglist_offset = ((SYMS_U32 *)offsets_arr)[index]; break;
1636 case 8: rnglist_offset = ((SYMS_U64 *)offsets_arr)[index]; break;
1637 }
1638 result = rnglist_offset+table_off;
1639 }
1640
1641 return result;
1642}
1643
1646{
1647 SYMS_U64RangeList list = {0};
1648
1649 SYMS_U64 read_off = offset;
1650 void *base = syms_dw_sec_base_from_dbg(data, dbg, section);
1652
1653 SYMS_U64 base_addr = 0;
1654
1655 for(SYMS_B32 done = syms_false; !done;)
1656 {
1657 SYMS_U8 kind8 = 0;
1660
1661 switch(kind)
1662 {
1663 //- rjf: can be used in split and non-split units:
1664 default:
1666 {
1667 done = syms_true;
1668 }break;
1669
1671 {
1675 }break;
1676
1678 {
1686 }break;
1687
1689 {
1691 SYMS_U64 length = 0;
1695 SYMS_U64 end_addr = start_addr + length;
1697 }break;
1698
1700 {
1702 SYMS_U64 end_offset = 0;
1704 read_off += syms_based_range_read_uleb128(base, rng, read_off, &end_offset);
1705 syms_u64_range_list_push(arena, &list, syms_make_u64_range(start_offset + base_addr, end_offset + base_addr));
1706 }break;
1707
1708 //- rjf: non-split units only:
1709
1711 {
1714 base_addr = new_base_addr;
1715 }break;
1716
1718 {
1719 SYMS_U64 start = 0;
1720 SYMS_U64 end = 0;
1721 read_off += syms_based_range_read(base, rng, read_off, addr_size, &start);
1722 read_off += syms_based_range_read(base, rng, read_off, addr_size, &end);
1724 }break;
1725
1727 {
1728 SYMS_U64 start = 0;
1729 SYMS_U64 length = 0;
1730 read_off += syms_based_range_read(base, rng, read_off, addr_size, &start);
1732 syms_u64_range_list_push(arena, &list, syms_make_u64_range(start, start+length));
1733 }break;
1734 }
1735 }
1736
1737 return list;
1738}
1739
1740//- rjf: .debug_loclists parsing
1741
1744{
1745 SYMS_LocRangeList list = {0};
1746
1747 SYMS_U64 read_off = offset;
1748 void *base = syms_dw_sec_base_from_dbg(data, dbg, section);
1750
1751 SYMS_U64 base_addr = 0;
1752
1753 for(SYMS_B32 done = syms_false; !done;)
1754 {
1755 SYMS_U8 kind8 = 0;
1758
1760 SYMS_U64 start_addr = 0;
1761 SYMS_U64 end_addr = 0;
1762
1763 switch(kind)
1764 {
1765 //- rjf: can be used in split and non-split units:
1766 default:
1768 {
1769 done = syms_true;
1770 }break;
1771
1773 {
1777 }break;
1778
1780 {
1788 }break;
1789
1791 {
1793 SYMS_U64 length = 0;
1797 end_addr = start_addr + length;
1799 }break;
1800
1802 {
1804 SYMS_U64 end_offset = 0;
1806 read_off += syms_based_range_read_uleb128(base, rng, read_off, &end_offset);
1807 start_addr = start_offset + base_addr;
1808 end_addr = end_offset + base_addr;
1810 }break;
1811
1813 {
1815 }break;
1816
1817 //- rjf: non-split units only:
1818
1820 {
1823 base_addr = new_base_addr;
1824 }break;
1825
1827 {
1828 SYMS_U64 start = 0;
1829 SYMS_U64 end = 0;
1830 read_off += syms_based_range_read(base, rng, read_off, addr_size, &start);
1831 read_off += syms_based_range_read(base, rng, read_off, addr_size, &end);
1832 start_addr = start;
1833 end_addr = end;
1835 }break;
1836
1838 {
1839 SYMS_U64 start = 0;
1840 SYMS_U64 length = 0;
1841 read_off += syms_based_range_read(base, rng, read_off, addr_size, &start);
1843 start_addr = start;
1844 end_addr = start+length;
1846 }break;
1847 }
1848
1849 //- rjf: parse a counted location description + push to result, if valid
1851 {
1856 SYMS_QueuePush(list.first, list.last, n);
1857 list.count += 1;
1858
1859 // rjf: skip past the location description
1863 }
1864 }
1865
1866 return list;
1867}
1868
1871{
1872 SYMS_Location result = {0};
1873
1874 void *base = syms_dw_sec_base_from_dbg(data, dbg, section);
1877 SYMS_U64 length = 0;
1882
1883 // TODO(rjf): wire up `location` to `result`, once SYMS_Location changes to
1884 // returning a SYMS_String8 instead of an op list.
1885
1886 return result;
1887}
1888
1890//~ rjf: Attrib Value Parsing
1891
1894{
1896 syms_memzero_struct(&params);
1897 params.version = root->version;
1898 params.language = root->language;
1899 params.addr_size = root->address_size;
1900 params.containing_unit_info_off = root->info_off;
1901 params.debug_addrs_base = root->addrs_base;
1902 params.debug_rnglists_base = root->rnglist_base;
1903 params.debug_str_offs_base = root->stroffs_base;
1904 params.debug_loclists_base = root->loclist_base;
1905 return params;
1906}
1907
1910 SYMS_DwFormKind form_kind, SYMS_DwAttribClass value_class,
1911 SYMS_DwAttribValue form_value)
1912{
1913 SYMS_DwAttribValue value;
1914 syms_memzero_struct(&value);
1915
1916 //~ rjf: DWARF V5 value parsing
1917
1918 //- rjf: (DWARF V5 ONLY) the form value is storing an address index (ADDRess indeX), which we
1919 // must resolve to an actual address using the containing comp unit's contribution to the
1920 // .debug_addr section.
1921 if(resolve_params.version >= SYMS_DwVersion_V5 &&
1922 value_class == SYMS_DwAttribClass_ADDRESS &&
1923 (form_kind == SYMS_DwFormKind_ADDRX || form_kind == SYMS_DwFormKind_ADDRX1 ||
1924 form_kind == SYMS_DwFormKind_ADDRX2 || form_kind == SYMS_DwFormKind_ADDRX3 ||
1925 form_kind == SYMS_DwFormKind_ADDRX4))
1926 {
1927 SYMS_U64 addr_index = form_value.v[0];
1929 value.v[0] = addr;
1930 }
1931 //- rjf: (DWARF V5 ONLY) lookup into the .debug_loclists section via an index
1932 else if(resolve_params.version >= SYMS_DwVersion_V5 &&
1933 value_class == SYMS_DwAttribClass_LOCLIST &&
1934 form_kind == SYMS_DwFormKind_LOCLISTX)
1935 {
1936 SYMS_U64 loclist_index = form_value.v[0];
1939 value.v[0] = loclist_offset;
1940 }
1941 //- rjf: (DWARF V5 ONLY) lookup into the .debug_loclists section via an offset
1942 else if(resolve_params.version >= SYMS_DwVersion_V5 &&
1943 (value_class == SYMS_DwAttribClass_LOCLIST ||
1944 value_class == SYMS_DwAttribClass_LOCLISTPTR) &&
1945 form_kind == SYMS_DwFormKind_SEC_OFFSET)
1946 {
1947 SYMS_U64 loclist_offset = form_value.v[0];
1949 value.v[0] = loclist_offset;
1950 }
1951 //- rjf: (DWARF V5 ONLY) lookup into the .debug_rnglists section via an index
1952 else if(resolve_params.version >= SYMS_DwVersion_V5 &&
1953 (value_class == SYMS_DwAttribClass_RNGLISTPTR ||
1954 value_class == SYMS_DwAttribClass_RNGLIST) &&
1955 form_kind == SYMS_DwFormKind_RNGLISTX)
1956 {
1957 SYMS_U64 rnglist_index = form_value.v[0];
1960 value.v[0] = rnglist_offset;
1961 }
1962 //- rjf: (DWARF V5 ONLY) lookup into the .debug_rnglists section via an offset
1963 else if(resolve_params.version >= SYMS_DwVersion_V5 &&
1964 (value_class == SYMS_DwAttribClass_RNGLISTPTR ||
1965 value_class == SYMS_DwAttribClass_RNGLIST) &&
1966 form_kind != SYMS_DwFormKind_RNGLISTX)
1967 {
1968 SYMS_U64 rnglist_offset = form_value.v[0];
1970 value.v[0] = rnglist_offset;
1971 }
1972 //- rjf: (DWARF V5 ONLY) .debug_str_offsets table index, that we need to resolve
1973 // using the containing compilation unit's contribution to the section
1974 else if(resolve_params.version >= SYMS_DwVersion_V5 &&
1975 value_class == SYMS_DwAttribClass_STRING &&
1976 (form_kind == SYMS_DwFormKind_STRX ||
1977 form_kind == SYMS_DwFormKind_STRX1 ||
1978 form_kind == SYMS_DwFormKind_STRX2 ||
1979 form_kind == SYMS_DwFormKind_STRX3 ||
1980 form_kind == SYMS_DwFormKind_STRX4))
1981 {
1982 SYMS_U64 str_index = form_value.v[0];
1985 void *base = syms_dw_sec_base_from_dbg(data, dbg, value.section);
1988 value.v[0] = str_offset;
1989 value.v[1] = value.v[0] + string.size;
1990 }
1991 //- rjf: (DWARF V5 ONLY) reference that we should resolve through ref_addr_desc
1992 else if(resolve_params.version >= SYMS_DwVersion_V5 &&
1993 value_class == SYMS_DwAttribClass_REFERENCE &&
1994 form_kind == SYMS_DwFormKind_REF_ADDR)
1995 {
1996 // TODO(nick): DWARF 5 @dwarf_v5
1997 }
1998 //- TODO(rjf): (DWARF V5 ONLY) reference resolution using the .debug_names section
1999 else if(resolve_params.version >= SYMS_DwVersion_V5 &&
2000 form_kind == SYMS_DwFormKind_REF_SIG8)
2001 {
2002 // TODO(nick): DWARF 5: We need to handle .debug_names section in order to resolve this value. @dwarf_v5
2003 value.v[0] = SYMS_U64_MAX;
2004 }
2005
2006 //~ rjf: All other value parsing (DWARF V4 and below)
2007
2008 //- rjf: reference to an offset relative to the compilation unit's info base
2009 else if (value_class == SYMS_DwAttribClass_REFERENCE &&
2010 (form_kind == SYMS_DwFormKind_REF1 ||
2011 form_kind == SYMS_DwFormKind_REF2 ||
2012 form_kind == SYMS_DwFormKind_REF4 ||
2013 form_kind == SYMS_DwFormKind_REF8 ||
2014 form_kind == SYMS_DwFormKind_REF_UDATA))
2015 {
2016 value.v[0] = resolve_params.containing_unit_info_off + form_value.v[0];
2017 }
2018
2019 //- rjf: info-section string -- this is a string that is just pasted straight
2020 // into the .debug_info section
2021 else if(value_class == SYMS_DwAttribClass_STRING && form_kind == SYMS_DwFormKind_STRING)
2022 {
2023 value = form_value;
2025 }
2026
2027 //- rjf: string-section string -- this is a string that's inside the .debug_str
2028 // section, and we've been provided an offset to it
2029 else if(value_class == SYMS_DwAttribClass_STRING &&
2030 (form_kind == SYMS_DwFormKind_STRP ||
2031 form_kind == SYMS_DwFormKind_STRP_SUP))
2032 {
2034 void *base = syms_dw_sec_base_from_dbg(data, dbg, value.section);
2036 SYMS_String8 string = syms_based_range_read_string(base, range, form_value.v[0]);
2037 value.v[0] = form_value.v[0];
2038 value.v[1] = value.v[0] + string.size;
2039 }
2040 //- rjf: line-string
2041 else if(value_class == SYMS_DwAttribClass_STRING && form_kind == SYMS_DwFormKind_LINE_STRP)
2042 {
2044 void *base = syms_dw_sec_base_from_dbg(data, dbg, value.section);
2046 SYMS_String8 string = syms_based_range_read_string(base, range, form_value.v[0]);
2047 value.v[0] = form_value.v[0];
2048 value.v[1] = value.v[0] + string.size;
2049 }
2050 //- rjf: .debug_ranges
2051 else if(resolve_params.version < SYMS_DwVersion_V5 &&
2052 (value_class == SYMS_DwAttribClass_RNGLISTPTR ||
2053 value_class == SYMS_DwAttribClass_RNGLIST) &&
2054 (form_kind == SYMS_DwFormKind_SEC_OFFSET))
2055 {
2056 SYMS_U64 ranges_offset = form_value.v[0];
2058 value.v[0] = ranges_offset;
2059 }
2060 //- rjf: .debug_loc
2061 else if(resolve_params.version < SYMS_DwVersion_V5 &&
2062 (value_class == SYMS_DwAttribClass_LOCLISTPTR ||
2063 value_class == SYMS_DwAttribClass_LOCLIST) &&
2064 (form_kind == SYMS_DwFormKind_SEC_OFFSET))
2065 {
2066 SYMS_U64 offset = form_value.v[0];
2068 value.v[0] = offset;
2069 }
2070 //- rjf: invalid attribute class
2071 else if(value_class == 0)
2072 {
2073 SYMS_ASSERT_PARANOID(!"attribute class was not resolved");
2074 }
2075 //- rjf: in all other cases, we can accept the form_value as the correct
2076 // representation for the parsed value, so we can just copy it over.
2077 else
2078 {
2079 value = form_value;
2080 }
2081
2082 return value;
2083}
2084
2087{
2088 SYMS_String8 string;
2089 syms_memzero_struct(&string);
2091 void *base = syms_dw_sec_base_from_dbg(data, dbg, section_kind);
2093 string.str = (SYMS_U8 *)syms_based_range_ptr(base, range, value.v[0]);
2094 string.size = value.v[1] - value.v[0];
2095 return string;
2096}
2097
2100{
2101 SYMS_U64RangeList list = {0};
2102 switch(ranges_value.section)
2103 {
2104 //- rjf: (DWARF V5 ONLY) .debug_rnglists offset
2106 {
2107 list = syms_dw_v5_range_list_from_rnglist_offset(arena, data, dbg, ranges_value.section, address_size, addr_section_base, ranges_value.v[0]);
2108 }break;
2109
2110 //- rjf: (DWARF V4 and earlier) .debug_ranges parsing
2112 {
2113 list = syms_dw_v4_range_list_from_range_offset(arena, data, dbg, address_size, comp_unit_base_addr, ranges_value.v[0]);
2114 }break;
2115
2116 //- rjf: fall back to trying to use low/high PCs
2117 default:
2118 {
2119 syms_u64_range_list_push(arena, &list, syms_make_u64_range(low_pc, high_pc));
2120 }break;
2121 }
2122 return list;
2123}
2124
2126//~ rjf: Tag Parsing
2127
2130{
2131 //- rjf: set up prereqs
2138
2139 //- rjf: set up read offsets
2140 SYMS_U64 info_read_off = info_off;
2141 SYMS_U64 abbrev_read_off = abbrev_off;
2142
2143 //- rjf: parse all attributes
2144 SYMS_DwAttribListParseResult result = {0};
2146 {
2148
2149 //- rjf: parse abbrev attrib info
2152 {
2155 good_abbrev = abbrev.id != 0;
2156 }
2157
2158 //- rjf: extract attrib info from abbrev
2159 SYMS_DwAttribKind attrib_kind = (SYMS_DwAttribKind)abbrev.id;
2160 SYMS_DwFormKind form_kind = (SYMS_DwFormKind)abbrev.sub_kind;
2161 SYMS_DwAttribClass attrib_class = syms_dw_pick_attrib_value_class(lang, ver, attrib_kind, form_kind);
2162
2163 //- rjf: parse the form value from the file
2164 SYMS_DwAttribValue form_value;
2165 syms_memzero_struct(&form_value);
2166 if(good_abbrev)
2167 {
2168 // NOTE(nick): This is a special case form. Basically it let's user to
2169 // define attribute form in the .debug_info.
2170 if(form_kind == SYMS_DwFormKind_INDIRECT)
2171 {
2175 }
2177 form_kind, abbrev.const_value, &form_value);
2179 }
2180
2181 //- rjf: push this parsed attrib to the list
2182 if(good_abbrev)
2183 {
2186 node->attrib.abbrev_id = abbrev.id;
2187 node->attrib.attrib_kind = attrib_kind;
2188 node->attrib.form_kind = form_kind;
2190 node->attrib.form_value = form_value;
2191 result.attribs.count += 1;
2192 SYMS_QueuePush(result.attribs.first, result.attribs.last, node);
2193 }
2194 }
2195
2196 result.max_info_off = info_read_off;
2198 return result;
2199}
2200
2203 SYMS_String8 data,
2204 SYMS_DwDbgAccel *dbg,
2205 SYMS_DwAbbrevTable abbrev_table,
2206 SYMS_DwLanguage lang,
2207 SYMS_DwVersion ver,
2208 SYMS_U64 address_size,
2210{
2215
2216 SYMS_DwTag *tag = syms_push_array_zero(arena, SYMS_DwTag, 1);
2217
2218 //- rjf: calculate .debug_info read cursor, relative to info range minimum
2219 SYMS_U64 info_read_off = info_offset - info_range.min;
2220
2221 //- rjf: read abbrev ID
2222 SYMS_U64 abbrev_id = 0;
2224 SYMS_B32 good_abbrev_id = abbrev_id != 0;
2225
2226 //- rjf: figure out abbrev offset for this ID
2228 if(good_abbrev_id)
2229 {
2230 abbrev_offset = syms_dw_abbrev_offset_from_abbrev_id(abbrev_table, abbrev_id);
2231 }
2232
2233 //- rjf: calculate .debug_abbrev read cursor, relative to abbrev range minimum
2234 SYMS_U64 abbrev_read_off = abbrev_offset - abbrev_range.min;
2235
2236 //- rjf: parse abbrev tag info
2240 if(good_abbrev_id)
2241 {
2243 good_tag_abbrev = syms_true;//abbrev_tag_info.id != 0;
2244 }
2245
2246 //- rjf: parse all attributes for this tag
2247 SYMS_U64 attribs_info_off = 0;
2248 SYMS_U64 attribs_abbrev_off = 0;
2249 SYMS_DwAttribList attribs = {0};
2250 if(good_tag_abbrev)
2251 {
2253 attribs_info_off = info_read_off;
2254 attribs_abbrev_off = abbrev_read_off;
2255 info_read_off = attribs_parse.max_info_off;
2256 abbrev_read_off = attribs_parse.max_abbrev_off;
2257 attribs = attribs_parse.attribs;
2258 }
2259
2260 //- rjf: fill tag
2261 {
2262 tag->abbrev_id = abbrev_id;
2266 tag->kind = (SYMS_DwTagKind)abbrev_tag_info.sub_kind;
2267 tag->attribs_info_off = attribs_info_off;
2268 tag->attribs_abbrev_off = attribs_abbrev_off;
2269 tag->attribs = attribs;
2270 }
2271
2272 return tag;
2273}
2274
2277 SYMS_DwTag *tag)
2278{
2279 SYMS_DwTagStub stub = {0};
2280 stub.sid = tag->info_range.min;
2281 stub.kind = tag->kind;
2282 stub.children_info_off = tag->has_children ? tag->info_range.max : 0;
2285 for(SYMS_DwAttribNode *n = tag->attribs.first; n != 0; n = n->next)
2286 {
2287 SYMS_DwAttrib *attrib = &n->attrib;
2288 switch(attrib->attrib_kind)
2289 {
2290 default: break;
2292 {
2293 SYMS_DwAttribValue value = syms_dw_attrib_value_from_form_value(data, dbg, resolve_params, attrib->form_kind, attrib->value_class, attrib->form_value);
2294 stub.ref = value.v[0];
2296 }break;
2298 {
2299 SYMS_DwAttribValue value = syms_dw_attrib_value_from_form_value(data, dbg, resolve_params, attrib->form_kind, attrib->value_class, attrib->form_value);
2300 stub.abstract_origin = value.v[0];
2301 }break;
2305 }
2306 }
2307 return stub;
2308}
2309
2311//~ rjf: Unit Set Accel;
2312
2315{
2316 // NOTE(rjf): From the DWARF V5 spec (February 13, 2017), page 401:
2317 //
2318 // "
2319 // Each skeleton compilation unit also has a DW_AT_addr_base attribute,
2320 // which provides the relocated offset to that compilation unit’s
2321 // contribution in the executable’s .debug_addr section. Unlike the
2322 // DW_AT_stmt_list attribute, the offset refers to the first address table
2323 // slot, not to the section header. In this example, we see that the first
2324 // address (slot 0) from demo1.o begins at offset 48. Because the
2325 // .debug_addr section contains an 8-byte header, the object file’s
2326 // contribution to the section actually begins at offset 40 (for a 64-bit
2327 // DWARF object, the header would be 16 bytes long, and the value for the
2328 // DW_AT_addr_base attribute would then be 56). All attributes in demo1.dwo
2329 // that use DW_FORM_addrx, DW_FORM_addrx1, DW_FORM_addrx2, DW_FORM_addrx3
2330 // or DW_FORM_addrx4 would then refer to address table slots relative to
2331 // that offset. Likewise, the .debug_addr contribution from demo2.dwo begins
2332 // at offset 72, and its first address slot is at offset 80. Because these
2333 // contributions have been processed by the linker, they contain relocated
2334 // values for the addresses in the program that are referred to by the
2335 // debug information.
2336 // "
2337 //
2338 // This seems to at least partially explain why the addr_base is showing up
2339 // 8 bytes later than we are expecting it to. We can't actually just store
2340 // the base that we read from the SYMS_DwAttribKind_ADDR_BASE attrib, because
2341 // it's showing up *after* the header, so we need to bump it back.
2342
2343 // NOTE(rjf): From the DWARF V5 spec (February 13, 2017), page 66:
2344 //
2345 // "
2346 // A DW_AT_rnglists_base attribute, whose value is of class rnglistsptr. This
2347 // attribute points to the beginning of the offsets table (immediately
2348 // following the header) of the compilation unit's contribution to the
2349 // .debug_rnglists section. References to range lists (using DW_FORM_rnglistx)
2350 // within the compilation unit are interpreted relative to this base.
2351 // "
2352 //
2353 // Similarly, we need to figure out where to go to parse the header.
2354
2357 switch(section)
2358 {
2359 default:
2361 {
2362 max_header_size = 16;
2363 min_header_size = 8;
2364 }break;
2366 {
2367 max_header_size = 16;
2368 min_header_size = 8;
2369 }break;
2371 {
2372 max_header_size = 20;
2373 min_header_size = 12;
2374 }break;
2376 {
2377 // TODO(rjf)
2378 }break;
2379 }
2380
2382 void *addr_base = syms_dw_sec_base_from_dbg(data, dbg, section);
2384
2385 //- rjf: figure out which sized header we have
2386 SYMS_U64 header_size = 0;
2387 {
2388 // rjf: try max header, and if it works, the header is the max size, otherwise we will
2389 // need to rely on the min header size
2390 SYMS_U32 first32 = 0;
2392 if(first32 == 0xffffffff)
2393 {
2394 header_size = max_header_size;
2395 }
2396 else
2397 {
2398 header_size = min_header_size;
2399 }
2400 }
2401
2402 return table_off - header_size;
2403}
2404
2407{
2410
2411 //- rjf: up-front known parsing offsets (yep, that's right, it's only 1!)
2412 SYMS_U64 size_off = 0;
2413
2414 //- rjf: parse size of this compilation unit's data
2415 SYMS_U64 size = 0;
2417 {
2420 }
2421
2422 //- rjf: parse version
2424 SYMS_U16 version = 0;
2427 {
2428 unit_off += sizeof(SYMS_U16);
2430 }
2431
2432 //- rjf: parse unit kind, abbrev_base, address size
2434 SYMS_U64 next_off = unit_off;
2437 SYMS_U64 address_size = 0;
2439 if(got_version)
2440 {
2441 switch(version)
2442 {
2443 default: break;
2444 case SYMS_DwVersion_V2: {
2445 abbrev_base = 0;
2446 next_off += syms_based_range_read(info_base, range, next_off, 4, &abbrev_base);
2447 next_off += syms_based_range_read(info_base, range, next_off, 1, &address_size);
2449 } break;
2450 case SYMS_DwVersion_V3:
2451 case SYMS_DwVersion_V4:
2452 {
2453 next_off += syms_dw_based_range_read_length(info_base, range, next_off, &abbrev_base);
2454 next_off += syms_based_range_read(info_base, range, next_off, 1, &address_size);
2456 }break;
2457 case SYMS_DwVersion_V5:
2458 {
2459 next_off += syms_based_range_read(info_base, range, next_off, 1, &unit_kind);
2460 next_off += syms_based_range_read(info_base, range, next_off, 1, &address_size);
2461 next_off += syms_dw_based_range_read_length(info_base, range, next_off, &abbrev_base);
2463
2464 //- rjf: parse DWO ID if appropriate
2466 {
2467 next_off += syms_based_range_read(info_base, range, next_off, 8, &spec_dwo_id);
2468 }
2469 }break;
2470 }
2471 }
2472
2473 //- rjf: build abbrev table
2474 SYMS_DwAbbrevTable abbrev_table = {0};
2475 if(got_unit_kind)
2476 {
2477 abbrev_table = syms_dw_make_abbrev_table(arena, data, dbg, abbrev_base);
2478 }
2479
2480 //- rjf: parse compilation unit's tag
2483 if(got_unit_kind)
2484 {
2485 SYMS_U64 comp_root_tag_off = range.min + next_off;
2486 comp_unit_tag = syms_dw_tag_from_info_offset(scratch.arena, data, dbg, abbrev_table, SYMS_DwLanguage_NULL, (SYMS_DwVersion)version, address_size, comp_root_tag_off);
2488 }
2489
2490 //- rjf: get all of the attribute values we need to start resolving attribute values
2491 SYMS_DwAttribValueResolveParams resolve_params;
2492 syms_memzero_struct(&resolve_params);
2493 resolve_params.version = (SYMS_DwVersion)version;
2495 {
2496 for(SYMS_DwAttribNode *attrib_n = comp_unit_tag->attribs.first; attrib_n; attrib_n = attrib_n->next)
2497 {
2498 SYMS_DwAttrib *attrib = &attrib_n->attrib;
2499
2500 // NOTE(rjf): We'll have to rely on just the form value at this point,
2501 // since we can't use the unit yet (since we're currently in the process
2502 // of building it). This should always be enough, otherwise there would
2503 // be a cyclic dependency in the requirements of each part of the
2504 // compilation unit's parse. DWARF is pretty crazy, but not *that* crazy,
2505 // so this should be good.
2506 switch(attrib->attrib_kind)
2507 {
2508 default: break;
2509 case SYMS_DwAttribKind_ADDR_BASE: {resolve_params.debug_addrs_base = attrib->form_value.v[0];}break;
2510 case SYMS_DwAttribKind_STR_OFFSETS_BASE: {resolve_params.debug_str_offs_base = attrib->form_value.v[0];}break;
2511 case SYMS_DwAttribKind_RNGLISTS_BASE: {resolve_params.debug_rnglists_base = attrib->form_value.v[0];}break;
2512 case SYMS_DwAttribKind_LOCLISTS_BASE: {resolve_params.debug_loclists_base = attrib->form_value.v[0];}break;
2513 }
2514 }
2515 }
2516
2517 //- rjf: correct table offsets to header offsets (since DWARF V5 insists on being as useless as possible)
2518 if(got_comp_unit_tag && version >= SYMS_DwVersion_V5)
2519 {
2521 resolve_params.debug_addrs_base);
2523 resolve_params.debug_str_offs_base);
2525 resolve_params.debug_loclists_base);
2527 resolve_params.debug_rnglists_base);
2528 }
2529
2530 //- rjf: parse the rest of the compilation unit tag's attributes that we'd
2531 // like to cache
2532 SYMS_String8 name = {0};
2533 SYMS_String8 producer = {0};
2534 SYMS_String8 compile_dir = {0};
2535 SYMS_String8 external_dwo_name = {0};
2537 SYMS_U64 gnu_dwo_id = 0;
2538 SYMS_U64 language = 0;
2539 SYMS_U64 name_case = 0;
2540 SYMS_B32 use_utf8 = 0;
2541 SYMS_U64 low_pc = 0;
2542 SYMS_U64 high_pc = 0;
2544 SYMS_DwAttribValue ranges_attrib_value = {SYMS_DwSectionKind_Null};
2545 SYMS_U64 line_base = 0;
2547 {
2548 for(SYMS_DwAttribNode *attrib_n = comp_unit_tag->attribs.first; attrib_n; attrib_n = attrib_n->next)
2549 {
2550 SYMS_DwAttrib *attrib = &attrib_n->attrib;
2551
2552 //- rjf: form value => value
2553 SYMS_DwAttribValue value;
2555 {
2556 syms_memzero_struct(&value);
2558 {
2559 value = syms_dw_attrib_value_from_form_value(data, dbg, resolve_params,
2560 attrib->form_kind,
2561 attrib->value_class,
2562 attrib->form_value);
2564 }
2565 }
2566
2567 //- rjf: map value to extracted info
2568 if(good_value)
2569 {
2570 switch(attrib->attrib_kind)
2571 {
2572 case SYMS_DwAttribKind_NAME: {name = syms_dw_string_from_attrib_value(data, dbg, value); }break;
2573 case SYMS_DwAttribKind_PRODUCER: {producer = syms_dw_string_from_attrib_value(data, dbg, value); }break;
2574 case SYMS_DwAttribKind_COMP_DIR: {compile_dir = syms_dw_string_from_attrib_value(data, dbg, value); }break;
2575 case SYMS_DwAttribKind_DWO_NAME: {external_dwo_name = syms_dw_string_from_attrib_value(data, dbg, value); }break;
2577 case SYMS_DwAttribKind_GNU_DWO_ID: {gnu_dwo_id = value.v[0]; }break;
2578 case SYMS_DwAttribKind_LANGUAGE: {language = value.v[0]; }break;
2579 case SYMS_DwAttribKind_IDENTIFIER_CASE: {name_case = value.v[0]; }break;
2580 case SYMS_DwAttribKind_USE_UTF8: {use_utf8 = (SYMS_B32)value.v[0]; }break;
2581 case SYMS_DwAttribKind_LOW_PC: {low_pc = value.v[0]; }break;
2582 case SYMS_DwAttribKind_HIGH_PC: {high_pc = value.v[0]; high_pc_is_relative = attrib->value_class != SYMS_DwAttribClass_ADDRESS;}break;
2583 case SYMS_DwAttribKind_RANGES: {ranges_attrib_value = value; }break;
2584 case SYMS_DwAttribKind_STMT_LIST: {line_base = value.v[0]; }break;
2585 default: break;
2586 }
2587 }
2588 }
2589 }
2590
2591 //- rjf: build+fill unit
2592 SYMS_DwCompRoot unit;
2593 syms_memzero_struct(&unit);
2594
2595 //- rjf: fill header data
2596 unit.size = size;
2598 unit.version = (SYMS_DwVersion)version;
2599 unit.address_size = address_size;
2600 unit.abbrev_off = abbrev_base;
2601 unit.info_off = range.min;
2602 unit.index = index;
2603 unit.tags_info_range = syms_make_u64_range(range.min+next_off, range.max);
2604 unit.abbrev_table = abbrev_table;
2605
2606 //- rjf: fill out offsets we need for attrib value resolution
2607 unit.rnglist_base = resolve_params.debug_rnglists_base;
2608 unit.loclist_base = resolve_params.debug_loclists_base;
2609 unit.addrs_base = resolve_params.debug_addrs_base;
2610 unit.stroffs_base = resolve_params.debug_str_offs_base;
2611
2612 //- rjf: fill out general info
2613 unit.name = name;
2614 unit.producer = producer;
2615 unit.compile_dir = compile_dir;
2616 unit.external_dwo_name = external_dwo_name.size != 0 ? external_dwo_name : external_gnu_dwo_name;
2617 if(external_dwo_name.size)
2618 {
2619 unit.dwo_id = spec_dwo_id;
2620 }
2621 else if(external_gnu_dwo_name.size)
2622 {
2623 unit.dwo_id = gnu_dwo_id;
2624 }
2625 unit.language = (SYMS_DwLanguage)language;
2626 unit.name_case = name_case;
2627 unit.use_utf8 = use_utf8;
2628 unit.line_off = line_base;
2629 unit.low_pc = low_pc;
2630 unit.high_pc = high_pc;
2631 unit.ranges_attrib_value = ranges_attrib_value;
2632
2633 //- rjf: fill fixup of low/high PC situation
2635 {
2636 unit.high_pc += unit.low_pc;
2637 }
2638
2639 //- rjf: fill base address
2640 {
2641 unit.base_addr = unit.low_pc;
2642 }
2643
2644 //- rjf: build+fill directory and file tables
2645 {
2647 void *line_base = syms_dw_sec_base_from_dbg(data, dbg, SYMS_DwSectionKind_Line);
2650 SYMS_U64 read_size = syms_dw_read_line_vm_header(arena, line_base, line_rng, unit.line_off, data, line_mode, dbg, &unit, &vm_header);
2651 if (read_size > 0) {
2652 unit.dir_table = vm_header.dir_table;
2653 unit.file_table = vm_header.file_table;
2654 }
2655 }
2656
2658 return unit;
2659}
2660
2663{
2665 syms_memzero_struct(&ref);
2666 ref.dwo_path = root->external_dwo_name;
2667 ref.dwo_id = root->dwo_id;
2668 return ref;
2669}
2670
2685
2688{
2689 return accel->root_count;
2690}
2691
2696 if(0 < num && num <= accel->root_count)
2697 {
2698 root = &accel->roots[uid-1];
2699 }
2700 return root;
2701}
2702
2708
2713
2727
2730{
2731 SYMS_UnitNames result = {0};
2733 result.source_file = syms_push_string_copy(arena, comp_root->name);
2734 result.compiler = syms_push_string_copy(arena, comp_root->producer);
2735 result.compile_dir = syms_push_string_copy(arena, comp_root->compile_dir);
2736 return(result);
2737}
2738
2739SYMS_API void
2741{
2743 SYMS_U64 right_i = right;
2744 for(SYMS_U64 idx = left; idx < end; idx += 1)
2745 {
2746 if(left_i < right && (right_i >= end || a[left_i].p <= a[right_i].p))
2747 {
2748 b[idx] = a[left_i];
2749 left_i += 1;
2750 }
2751 else
2752 {
2753 b[idx] = a[right_i];
2754 right_i += 1;
2755 }
2756 }
2757}
2758
2759SYMS_API void
2780
2783{
2785
2786 SYMS_U64 unit_count = dbg->unit_count;
2787 SYMS_U64RangeList *unit_ranges = syms_push_array_zero(scratch.arena, SYMS_U64RangeList, unit_count);
2788
2789 //- rjf: fill ranges that came from the .debug_aranges section
2790 for(SYMS_U64 unit_idx = 0; unit_idx < unit_count; unit_idx += 1)
2791 {
2793 {
2795 }
2796 }
2797
2798 //- rjf: fill range list for all compilation unit ranges/low-pc/high-pc data
2799 //
2800 // NOTE(rjf): .debug_aranges is apparently not entirely complete, and will not
2801 // include all the ranges we care about. The LLVM function (at 9/14/2021)
2802 // DWARFDebugAranges::generate seems to suggest this. We also need to rely on
2803 // the DW_AT_ranges and DW_AT_low_pc/high_pc attributes to build a complete
2804 // mapping of all compilation unit ranges.
2805 //
2806 for(SYMS_U64 unit_idx = 0; unit_idx < unit_count; unit_idx += 1)
2807 {
2810 root->address_size,
2811 root->base_addr,
2812 root->addrs_base,
2813 root->low_pc,
2814 root->high_pc,
2815 root->ranges_attrib_value);
2816 syms_u64_range_list_concat(&unit_ranges[unit_idx], &rngs);
2817 }
2818
2819 //- rjf: calc num of all ranges
2820 SYMS_U64 range_count = 0;
2821 for(SYMS_U64 unit_idx = 0; unit_idx < unit_count; unit_idx += 1)
2822 {
2823 range_count += unit_ranges[unit_idx].node_count;
2824 }
2825
2826 //- rjf: bake
2827 SYMS_UnitRange *ranges = syms_push_array_zero(scratch.arena, SYMS_UnitRange, range_count);
2828 {
2829 SYMS_UnitRange *range_ptr = ranges;
2830 for(SYMS_U64 unit_idx = 0; unit_idx < unit_count; unit_idx += 1)
2831 {
2832 for(SYMS_U64RangeNode *n = unit_ranges[unit_idx].first; n != 0; n = n->next)
2833 {
2834 range_ptr->uid = unit_idx + 1;
2835 range_ptr->vrange = n->range;
2836 range_ptr += 1;
2837 }
2838 }
2839 }
2840
2841 //- rjf: pointify
2842 SYMS_U64 rng_point_count = range_count*2;
2844 {
2846 for(SYMS_U64 rng_idx = 0; rng_idx < range_count; rng_idx += 1)
2847 {
2848 SYMS_U64Range vrange = ranges[rng_idx].vrange;
2849 SYMS_UnitID uid = ranges[rng_idx].uid;
2850 if(vrange.min != 0xffffffffffffffff && vrange.min != 0 && syms_u64_range_size(vrange) != 0)
2851 {
2854 rng_points[rng_point_write_idx].is_min = 1;
2858 rng_points[rng_point_write_idx].is_min = 0;
2860 }
2861 }
2863 }
2864
2865 //- rjf: sort pointified ranges
2866#if 1
2868#else
2869 for(SYMS_U64 i = 0; i < rng_point_count; i += 1)
2870 {
2871 SYMS_U64 min_idx = 0;
2872 SYMS_U64 min_p = 0;
2873 for(SYMS_U64 j = i+1; j < rng_point_count; j += 1)
2874 {
2875 if(min_idx == 0 || rng_points[j].p < min_p)
2876 {
2877 min_idx = j;
2878 min_p = rng_points[j].p;
2879 }
2880 }
2881 if(min_idx != 0)
2882 {
2884 }
2885 }
2886#endif
2887
2888 //- rjf: build final range list, collapse pairs into ranges
2891 {
2893 SYMS_UnitID uid;
2894 SYMS_U64Range vrange;
2895 };
2899 {
2900 if(rng_point_count > 0)
2901 {
2904 SYMS_U64 depth = 1;
2905 SYMS_U64 last_max = 0;
2906 for(SYMS_U64 p_idx = 1; p_idx < rng_point_count; p_idx += 1)
2907 {
2908 SYMS_B32 push = syms_false;
2911
2912 //- rjf: point in the same UID
2913 if(rng_points[p_idx].uid == active_uid)
2914 {
2915 // rjf: min => nested UID range, ignore + increase depth
2916 if(rng_points[p_idx].is_min)
2917 {
2918 depth += 1;
2919 }
2920 // rjf: max => end of some range, decrement depth and add new range if we're out of all hierarchies
2921 else
2922 {
2923 depth -= 1;
2924 if(depth == 0)
2925 {
2926 push = syms_true;
2929 active_uid = 0;
2930 active_rng_min = 0;
2931 }
2932 }
2933 }
2934 //- rjf: different uid + new min, end existing range + start a new one
2935 else if(rng_points[p_idx].is_min)
2936 {
2937 if(active_uid != 0)
2938 {
2939 push = syms_true;
2942 }
2945 depth = 1;
2946 }
2947 //- rjf: max for UID we're not focusing --- this generally means we were "interrupted" by
2948 // another UID -- so take the last max we produced, and make a range out of it
2949 else if(last_max != 0)
2950 {
2951 push = syms_true;
2953 push_uid = rng_points[p_idx].uid;
2954 active_uid = 0;
2955 active_rng_min = 0;
2956 depth = 0;
2957 }
2958
2959 //- rjf: push if we got a new range
2960 if(push && push_vrange.min != 0xffffffffffffffff && push_vrange.min != 0 && syms_u64_range_size(push_vrange) != 0)
2961 {
2963 n->uid = push_uid;
2964 n->vrange = push_vrange;
2967 last_max = push_vrange.max;
2968 }
2969 }
2970 }
2971 }
2972
2973 //- rjf: bake+fill+return
2974 SYMS_UnitRangeArray result = {0};
2975 {
2978 result.ranges = syms_push_array_zero(arena, SYMS_UnitRange, result.count);
2979 SYMS_U64 idx = 0;
2980 for(SYMS_DwUnitRangeNode *n = first_unit_range_node; n != 0; n = n->next, idx += 1)
2981 {
2982 result.ranges[idx].uid = n->uid;
2983 result.ranges[idx].vrange = n->vrange;
2984 SYMS_Log("$rng: %i => [0x%" SYMS_PRIx64 ", 0x%" SYMS_PRIx64 ")\n", (int)n->uid, n->vrange.min, n->vrange.max);
2985 }
2986 SYMS_LogClose(log);
2987 }
2989 return result;
2990}
2991
2994 SYMS_DwUnitSetAccel *unit_set, SYMS_UnitID uid)
2995{
2996 SYMS_String8Array result = {0};
2997 SYMS_DwCompRoot *root = syms_dw_comp_root_from_uid(unit_set, uid);
2998 if(root->file_table.count != 0)
2999 {
3002
3003 SYMS_String8 *string_ptr = strings;
3004 for(SYMS_U64 idx = 0; idx < count; idx += 1, string_ptr += 1)
3005 {
3006 SYMS_DwLineFile file = root->file_table.v[idx];
3007 SYMS_String8 dir_string = root->dir_table.strings[file.dir_idx];
3010 }
3011
3012 result.strings = strings;
3013 result.count = count;
3014 }
3015 return(result);
3016}
3017
3019//~ rjf: Tag Reference Data Structure
3020
3023{
3024 SYMS_DwTagRefTable table = {0};
3025 table.size = size;
3026 table.v = syms_push_array_zero(arena, SYMS_DwTagRefNode *, size);
3027 return table;
3028}
3029
3030SYMS_API void
3032{
3034 SYMS_U64 idx = hash % table->size;
3036 n->dst = dst;
3037 n->src = src;
3038 SYMS_StackPush_N(table->v[idx], n, hash_next);
3039}
3040
3043{
3044 SYMS_SymbolID result = {0};
3046 SYMS_U64 idx = hash % table.size;
3047 for(SYMS_DwTagRefNode *n = table.v[idx]; n != 0; n = n->hash_next)
3048 {
3049 if(n->dst == dst)
3050 {
3051 result = n->src;
3052 break;
3053 }
3054 }
3055 return result;
3056}
3057
3059//~ rjf: Unit Symbol Accelerator
3060
3063{
3065 {
3066 4073, 5821, 7369, 7919, 8971, 10687, 13217, 14639, 16193, 17389, 19373,
3067 22123, 24517, 26029, 27259, 29633, 32917, 35381, 37139, 37813, 39631,
3068 42641, 45263, 47653, 54037, 57119, 59183, 62927, 66103, 69389, 70657,
3069 72467, 76819, 80051, 84017, 87071, 93179, 97303, 99817, 102397, 104677,
3070 112967, 116371, 128111, 161407, 178301, 187963, 200003, 249439, 312583,
3071 411637, 466019, 545959, 745709, 796571, 862177, 918539, 1032683, 1187239,
3072 1213633, 1299827,
3073 };
3074 SYMS_U64 result = 0;
3075 SYMS_U64 low = 0;
3077 for(;;)
3078 {
3079 SYMS_U64 mid = (high + low) / 2;
3080 SYMS_U64 left = mid > 0 ? primes[mid-1] : 4073;
3081 SYMS_U64 right = primes[mid];
3082 if(left <= v && v <= right)
3083 {
3084 result = left;
3085 break;
3086 }
3087 else if(v < left)
3088 {
3089 high = mid;
3090 }
3091 else if(right < v)
3092 {
3093 low = mid;
3094 }
3095 }
3096 return result;
3097}
3098
3101{
3102 // NOTE(rjf): currently, we're caching somewhere around ~25% of the tags we parse;
3103 // so we only need table size for that
3104 SYMS_F64 pct_cached = 0.2;
3105
3106 SYMS_F64 size_f = (SYMS_F64)size;
3107 SYMS_F64 a = -0.0000000001700537876;
3108 SYMS_F64 b = 0.1051854269;
3109 SYMS_F64 c = 3748.774284;
3110 SYMS_F64 table_size_f = (a * size_f*size_f) + (b * size_f) + c;
3116 return table_size;
3117}
3118
3121{
3122 SYMS_ProfBegin("syms_dw_unit_accel_from_comp_root");
3125 syms_memzero_struct(unit);
3126
3127 //- rjf: initialize accelerator
3128 unit->format = dbg->format;
3129 unit->uid = comp_root->index + 1;
3130 unit->version = comp_root->version;
3131 unit->address_size = comp_root->address_size;
3132 unit->base_addr = comp_root->base_addr;
3133 unit->addrs_base = comp_root->addrs_base;
3134 unit->language = comp_root->language;
3135 unit->abbrev_table.count = comp_root->abbrev_table.count;
3137 sizeof(SYMS_DwAbbrevTableEntry) * unit->abbrev_table.count)).str;
3138 unit->stub_table_size = syms_dw_predict_good_stub_table_size_from_range_size(comp_root->tags_info_range.max - comp_root->tags_info_range.min);
3140 // TODO(rjf): This is an arbitrary choice of size. Can we predict it? Or tune it to
3141 // common cases at least?
3142 unit->ref_table = syms_dw_tag_ref_table_make(arena, 4096);
3143 // TODO(rjf): This is an arbitrary choice of size. Can we predict it? Or tune it to
3144 // common cases at least?
3145 unit->parent_table = syms_dw_tag_ref_table_make(arena, 4096);
3147
3148 //- rjf: parse loop
3152 SYMS_DwSymbolIDChunkList proc_ids = {0};
3153 SYMS_DwSymbolIDChunkList var_ids = {0};
3154 SYMS_DwSymbolIDChunkList type_ids = {0};
3155 {
3157 struct SYMS_DwParseParent
3158 {
3162 };
3164 SYMS_U64 tree_depth = 0;
3165
3166 for(SYMS_U64 info_off = comp_root->tags_info_range.min; info_off < comp_root->tags_info_range.max;)
3167 {
3168 SYMS_Arena *conflicts[] = { scratch.arena, arena };
3170
3171 //- rjf: parse tag
3172 SYMS_DwTag *tag = syms_dw_tag_from_info_offset(per_tag_scratch.arena, data, dbg, comp_root->abbrev_table, comp_root->language, comp_root->version, comp_root->address_size, info_off);
3173 SYMS_B32 good_tag = tag->abbrev_id != 0;
3174 info_off = tag->info_range.max;
3175 if(good_tag)
3176 {
3177 tags_parsed += 1;
3178 }
3179
3180 //- rjf: convert tag to stub
3181 SYMS_DwTagStub stub = {0};
3182 if(good_tag)
3183 {
3184 stub = syms_dw_stub_from_tag(data, dbg, unit->resolve_params, tag);
3185 }
3186
3187 //- rjf: classify + store ID into classification lists
3188 if(good_tag)
3189 {
3191 switch(symbol_kind)
3192 {
3193 default: break;
3194 case SYMS_SymbolKind_Procedure: syms_dw_symbol_id_chunk_list_push(scratch.arena, &proc_ids, stub.sid); break;
3195 case SYMS_SymbolKind_Type: syms_dw_symbol_id_chunk_list_push(scratch.arena, &type_ids, stub.sid); break;
3197 }
3198 if(tree_depth <= 1 ||
3202 {
3204 }
3205 }
3206
3207 //- rjf: determine if this tag should be cached
3209 if(good_tag)
3210 {
3211 // NOTE(rjf): only cache nodes when we either don't have any parents at all
3212 // (in which case we need to make some), or when our active parent was cached
3213 // also.
3214 should_be_cached = parent_stack == 0 || parent_stack->parent != 0;
3215
3216 // NOTE(rjf): any of the listed tag kinds will not be cached, and will be re-parsed
3217 // upon being queried by a caller:
3218 switch(tag->kind)
3219 {
3220 default: break;
3221
3233
3234 //case SYMS_DwTagKind_STRUCTURE_TYPE:
3235 //case SYMS_DwTagKind_CLASS_TYPE:
3236 //case SYMS_DwTagKind_UNION_TYPE:
3237 //case SYMS_DwTagKind_ENUMERATION_TYPE:
3238 //case SYMS_DwTagKind_SUBPROGRAM:
3243 //case SYMS_DwTagKind_SUBPROGRAM:
3244 {
3245 should_be_cached = 0;
3246 }break;
3247 }
3248 }
3249
3250 //- rjf: allocate/fill cache node
3253 {
3255 stub_node->stub = stub;
3256 }
3257
3258 //- rjf: link stub cache node into hash table
3259 if(stub_node != 0)
3260 {
3262 SYMS_U64 hash = syms_dw_hash_from_sid(stub_node->stub.sid);
3263 SYMS_U64 idx = hash % unit->stub_table_size;
3264 // printf("%16" SYMS_PRIu64 ", %16" SYMS_PRIu64 ", %16" SYMS_PRIu64 ", %16" SYMS_PRIu64 "\n", stub_node->stub.sid, hash, idx, unit->stub_table_size);
3265 stub_node->hash_next = unit->stub_table[idx];
3266 unit->stub_table[idx] = stub_node;
3267 }
3268
3269 //- rjf: insert stub cache node into tree
3270 if(stub_node != 0)
3271 {
3272 if(parent_stack)
3273 {
3275 for(SYMS_DwParseParent *p = parent_stack; p != 0; p = p->next)
3276 {
3277 if(p->parent)
3278 {
3279 closest_ancestor = p->parent;
3280 break;
3281 }
3282 }
3284 {
3286 closest_ancestor->children_count += 1;
3287 }
3288 }
3289 if(unit->stub_root == 0)
3290 {
3291 unit->stub_root = stub_node;
3292 }
3293 }
3294
3295 // NOTE(rjf): Sometimes, DWARF splits info for a single symbol across multiple
3296 // tags. In this case, we'll have an earlier tag (which may or may not be
3297 // cached) that is completed by another tag that points to it. This is pretty
3298 // inconvenient, because we often watn to go the other direction -- from the
3299 // earlier tag *to* its completion, so we can get full info from either
3300 // direction. Usually these are only pairs, it seems - there is usually only
3301 // one specification per tag that has any (I have not seen any cases to the
3302 // contrary, at least). A tag with the SYMS_DwAttribKind_SPECIFICATION attrib
3303 // should always come *AFTER* the tag of the associated declaration.
3304 //
3305 // For more info, see DWARF V4 spec (June 10, 2010), page 36.
3306 //
3307 // In any case, here we've found a tag that is "completing" an earlier tag.
3308 // That earlier tag may not have been cached, so we cannot simply write to
3309 // that earlier tag and expect everything to be OK. If that earlier tag was
3310 // not cached, we'll need to cache the fact that it was referenced, and then
3311 // any time we get a tag stub (either from the cache or from reparsing), we
3312 // can functionally query that table and always get correct results,
3313 // irrespective of what was cached when.
3314 //
3315 // In short, we can't get away with not caching something here, because of
3316 // the fact that we're parsing a relationship between two seemingly-unrelated
3317 // (at least with respect to the tree structure) symbol IDs.
3318 //
3319 // We *can* write to the completed tag stub *if it was cached*, but otherwise
3320 // caching the reference into the table is necessary.
3321 //
3322 if(stub.ref != 0)
3323 {
3325 // NOTE(rjf): if we cached the tag that is being referenced, we can
3326 // write to its reference slot here to point back at this tag.
3327 if(ref_node != 0)
3328 {
3329 ref_node->stub.ref = stub.sid;
3330 }
3331 // NOTE(rjf): otherwise, we'll need to remember this link being formed
3332 // later so that when we query the completed tag, we'll figure out who
3333 // completed it.
3334 else
3335 {
3336 syms_dw_tag_ref_table_insert(arena, &unit->ref_table, stub.sid, stub.ref);
3337 }
3338 }
3339
3340 //- rjf: fill out parent ref for UDTs that might add a namespace
3341 if(stub.sid != 0 &&
3342 parent_stack != 0 &&
3343 parent_stack->parent_stub.sid != 0 &&
3344 (parent_stack->parent_stub.kind == SYMS_DwTagKind_STRUCTURE_TYPE ||
3345 parent_stack->parent_stub.kind == SYMS_DwTagKind_UNION_TYPE ||
3346 parent_stack->parent_stub.kind == SYMS_DwTagKind_CLASS_TYPE))
3347 {
3348 syms_dw_tag_ref_table_insert(arena, &unit->parent_table, parent_stack->parent_stub.sid, stub.sid);
3349 }
3350
3351 //- rjf: update parent
3353 {
3354 // NOTE(rjf): good tag with children => push this artifact as parent
3355 if(good_tag)
3356 {
3357 if(tag->has_children)
3358 {
3361 n->parent = stub_node;
3362 n->parent_stub = stub;
3363 tree_depth += 1;
3364 }
3365 }
3366 // NOTE(rjf): bad tag => if there's an active parent, go back up to its parent.
3367 // otherwise, we are done
3368 else
3369 {
3370 if(parent_stack != 0)
3371 {
3372 parent_stack = parent_stack->next;
3373 tree_depth -= 1;
3374 }
3375 }
3377 }
3378
3380 if(good_parent == 0)
3381 {
3382 break;
3383 }
3384 }
3385 }
3386
3387 //- rjf: construct synthetic stub for void type
3388 {
3393 void_stub_node->stub = void_stub;
3394
3395 //- rjf: link into tree
3397 unit->stub_root->children_count += 1;
3398
3399 //- rjf: link into hash table
3401 SYMS_U64 idx = hash % unit->stub_table_size;
3402 void_stub_node->hash_next = unit->stub_table[idx];
3403 unit->stub_table[idx] = void_stub_node;
3404
3407 }
3408
3409 //- rjf: fill classified top-level symbol arrays
3410 {
3411 SYMS_ProfBegin("syms_dw_unit_accel_from_comp_root.top_level_array_build");
3413 unit->proc_ids = syms_dw_sid_array_from_chunk_list(arena, proc_ids);
3414 unit->var_ids = syms_dw_sid_array_from_chunk_list(arena, var_ids);
3415 unit->type_ids = syms_dw_sid_array_from_chunk_list(arena, type_ids);
3416 SYMS_ProfEnd();
3417 }
3418
3419 //- rjf: log statistics about which tag kinds were cached
3420#if RJF_DEBUG && 0
3421 {
3423 SYMS_Log("$tag_profile\n");
3424
3425 // NOTE(rjf): pct odd hashes vs. pct even hashes
3426#if 0
3427 {
3428 SYMS_U64 odd = 0;
3429 SYMS_U64 even = 0;
3430 SYMS_U64 total = 0;
3431 for(SYMS_U64 idx = 0; idx < unit->stub_table_size; idx += 1)
3432 {
3433 for(SYMS_DwTagStubCacheNode *n = unit->stub_table[idx]; n != 0; n = n->hash_next)
3434 {
3435 total += 1;
3436 SYMS_U64 hash = syms_dw_hash_from_sid(n->stub.sid);
3437 if(hash & 1)
3438 {
3439 odd += 1;
3440 }
3441 else
3442 {
3443 even += 1;
3444 }
3445 }
3446 }
3447 printf("%16f %16f\n", (SYMS_F32)odd / total, (SYMS_F32)even / total);
3448 }
3449#endif
3450
3451 // NOTE(rjf): size, # of empty buckets, # of buckets total
3452#if 0
3453 {
3454 SYMS_U64 zeroes = 0;
3455 for(SYMS_U64 idx = 0; idx < unit->stub_table_size; idx += 1)
3456 {
3457 if(unit->stub_table[idx] == 0)
3458 {
3459 zeroes += 1;
3460 }
3461 }
3462 printf("%16" SYMS_PRIu64 " %16" SYMS_PRIu64 " %16" SYMS_PRIu64 "\n", comp_root->tags_info_range.max-comp_root->tags_info_range.min, zeroes,
3463 unit->stub_table_size);
3464 }
3465#endif
3466
3467 // NOTE(rjf): size, ratio of buckets filled, ratio of stubs vs. table size
3468#if 0
3469 {
3470 SYMS_U64 count = 0;
3471 SYMS_U64 zeroes = 0;
3472 for(SYMS_U64 idx = 0; idx < unit->stub_table_size; idx += 1)
3473 {
3474 if(unit->stub_table[idx] == 0)
3475 {
3476 zeroes += 1;
3477 }
3478 for(SYMS_DwTagStubCacheNode *n = unit->stub_table[idx]; n != 0; n = n->hash_next)
3479 {
3480 count += 1;
3481 }
3482 }
3483 printf("%24" SYMS_PRIu64 ", %24f, %24f, %24f\n",
3484 comp_root->tags_info_range.max-comp_root->tags_info_range.min,
3485 1.f - (SYMS_F32)zeroes / (SYMS_F32)unit->stub_table_size,
3488 }
3489#endif
3490
3491 // NOTE(rjf): size, # of collisions
3492#if 0
3493 {
3494 SYMS_U64 collisions = 0;
3495 for(SYMS_U64 idx = 0; idx < unit->stub_table_size; idx += 1)
3496 {
3498 for(SYMS_DwTagStubCacheNode *n = unit->stub_table[idx]; n != 0; n = n->hash_next)
3499 {
3500 if(n->hash_next)
3501 {
3503 }
3504 }
3506 }
3507 printf("%16" SYMS_PRIu64 " %16" SYMS_PRIu64 "\n", comp_root->tags_info_range.max-comp_root->tags_info_range.min, collisions);
3508 }
3509#endif
3510
3511 // NOTE(rjf): table stats
3512#if 0
3513 {
3516 SYMS_U64 zeroes = 0;
3517 SYMS_U64 n = 0;
3519 SYMS_F64 avg = 0;
3520 for(SYMS_U64 idx = 0; idx < unit->stub_table_size; idx += 1)
3521 {
3522 SYMS_U64 length = 0;
3523 for(SYMS_DwTagStubCacheNode *n = unit->stub_table[idx]; n != 0; n = n->hash_next)
3524 {
3525 length += 1;
3526 }
3527 num_cached += length;
3528 if(length > 0)
3529 {
3531 avg *= n;
3532 avg += length;
3533 n += 1;
3534 avg /= n;
3535 }
3536 else
3537 {
3538 zeroes += 1;
3539 }
3540 }
3541
3544 SYMS_F64 var_n = 0;
3545 {
3546 for(SYMS_U64 idx = 0; idx < unit->stub_table_size; idx += 1)
3547 {
3548 SYMS_U64 length = 0;
3549 for(SYMS_DwTagStubCacheNode *n = unit->stub_table[idx]; n != 0; n = n->hash_next)
3550 {
3551 length += 1;
3552 }
3553 SYMS_F64 diff = (SYMS_F64)length - load_factor;
3557 var_n += 1;
3559 }
3560 }
3561
3562 printf("range_size: %8" SYMS_PRIu64 " | table_size: %7" SYMS_PRIu64 " | num_cached: %11" SYMS_PRIu64 " (%8.2f%%) | num_parsed: %8" SYMS_PRIu64 " | num_zeroes: %7" SYMS_PRIu64 " (%8.2f%%) | avg_chain_length: %8f | worst_case_chain: %3" SYMS_PRIu64 " | avg_load_variance: %8f\n",
3563 comp_root->tags_info_range.max-comp_root->tags_info_range.min,
3564 table_size,
3565 num_cached,
3566 100.f * (SYMS_F32)num_cached / table_size,
3568 zeroes,
3569 100.f * (SYMS_F32)zeroes / table_size,
3570 avg,
3573
3574 // printf("%16" SYMS_PRIu64 " %16f\n", comp_root->tags_info_range.max-comp_root->tags_info_range.min, avg);
3575 }
3576#endif
3577
3578 // NOTE(rjf): size, avg chain length
3579#if 0
3580 {
3581 SYMS_U64 n = 0;
3582 SYMS_F32 avg = 0;
3583 for(SYMS_U64 idx = 0; idx < unit->stub_table_size; idx += 1)
3584 {
3585 SYMS_U64 length = 0;
3586 for(SYMS_DwTagStubCacheNode *n = unit->stub_table[idx]; n != 0; n = n->next)
3587 {
3588 length += 1;
3589 }
3590 if(length > 0)
3591 {
3592 avg *= n;
3593 avg += length;
3594 n += 1;
3595 avg /= n;
3596 }
3597 }
3598 printf("%16" SYMS_PRIu64 " %16f\n", comp_root->tags_info_range.max-comp_root->tags_info_range.min, avg);
3599 }
3600#endif
3601
3602 // NOTE(rjf): size, # of tags
3603#if 0
3604 {
3605 printf("%24" SYMS_PRIu64 ", %24" SYMS_PRIu64 ", %24" SYMS_PRIu64 "\n", comp_root->tags_info_range.max-comp_root->tags_info_range.min, tags_parsed, unit->stub_table_size);
3606 }
3607#endif
3608
3611 SYMS_U64 total = 0;
3612 for(SYMS_U64 idx = 0; idx < unit->all_top_ids.count; idx += 1)
3613 {
3615 if(cache_node != 0 && cache_node->stub.kind < tag_kind_counts_size)
3616 {
3617 tag_kind_counts[cache_node->stub.kind] += 1;
3618 total += 1;
3619 }
3620 }
3621
3623 {
3624 if(tag_kind_counts[tag_kind] != 0)
3625 {
3629 }
3630 }
3631
3632 SYMS_LogClose(log);
3633 }
3634#endif
3635
3636 SYMS_ProfEnd();
3638 return unit;
3639}
3640
3643 SYMS_DwDbgAccel *dbg,
3644 SYMS_DwUnitSetAccel *unit_set,
3645 SYMS_UnitID uid){
3648 return(result);
3649}
3650
3653{
3654 SYMS_UnitID id = unit->uid;
3655 return id;
3656}
3657
3660{
3661 SYMS_DwTagStubCacheNode *result = 0;
3662 SYMS_U64 hash = syms_dw_hash_from_sid(sid);
3663 SYMS_U64 idx = hash % unit->stub_table_size;
3664 for(SYMS_DwTagStubCacheNode *n = unit->stub_table[idx]; n != 0; n = n->hash_next)
3665 {
3666 if(n->stub.sid == sid)
3667 {
3668 result = n;
3669 break;
3670 }
3671 }
3672 return result;
3673}
3674
3677{
3678 SYMS_DwTagStub stub = {0};
3680 SYMS_DwTag *tag = syms_dw_tag_from_info_offset(scratch.arena, data, dbg, unit->abbrev_table, unit->language, unit->version, unit->address_size, sid);
3681 stub = syms_dw_stub_from_tag(data, dbg, unit->resolve_params, tag);
3682 if(stub.ref == 0)
3683 {
3686 }
3688 return stub;
3689}
3690
3693{
3694 SYMS_DwTagStub stub = {0};
3695 if(sid != 0)
3696 {
3698 if(n != 0)
3699 {
3700 stub = n->stub;
3701 }
3702 else
3703 {
3704 stub = syms_dw_tag_stub_from_sid(data, dbg, unit, sid);
3705 }
3706 }
3707 return stub;
3708}
3709
3712{
3715 if(cache_node != 0)
3716 {
3718 {
3720 n->stub = child->stub;
3721 SYMS_QueuePush(list.first, list.last, n);
3722 list.count += 1;
3723 }
3724 }
3725 else if(stub.children_info_off != 0)
3726 {
3728 SYMS_U64 depth = 0;
3729 for(SYMS_U64 info_off = stub.children_info_off;;)
3730 {
3731 SYMS_DwTag *child_tag = syms_dw_tag_from_info_offset(scratch.arena, data, dbg, unit->abbrev_table, unit->language, unit->version, unit->address_size, info_off);
3732 info_off = child_tag->info_range.max;
3733
3734 if(depth == 0 && child_tag->kind != SYMS_DwTagKind_NULL)
3735 {
3737 n->stub = syms_dw_stub_from_tag(data, dbg, unit->resolve_params, child_tag);
3739 SYMS_QueuePush(list.first, list.last, n);
3740 list.count += 1;
3741 }
3742
3743 if(child_tag->has_children)
3744 {
3745 depth += 1;
3746 }
3747 else if(child_tag->kind == SYMS_DwTagKind_NULL)
3748 {
3749 if(depth == 0)
3750 {
3751 break;
3752 }
3753 depth -= 1;
3754 }
3755 }
3757 }
3758 return list;
3759}
3760
3767
3770{
3771 SYMS_SymbolIDArray result = {0};
3772 result.count = arr.count;
3773 result.ids = syms_push_array(arena, SYMS_SymbolID, result.count);
3774 syms_memmove(result.ids, arr.ids, sizeof(SYMS_SymbolID)*result.count);
3775 return result;
3776}
3777
3783
3789
3795
3797//~ rjf: Member Accelerator
3798
3802{
3804
3810 {
3811 SYMS_DwTagStubList children = syms_dw_children_from_tag_stub(scratch.arena, data, dbg, unit, stub);
3813 accel->format = SYMS_FileFormat_DWARF;
3814 accel->count = children.count;
3815 accel->mem_infos = syms_push_array_zero(arena, SYMS_MemInfo, accel->count);
3816 accel->type_symbols = syms_push_array_zero(arena, SYMS_USID, accel->count);
3817 accel->full_symbols = syms_push_array_zero(arena, SYMS_USID, accel->count);
3818 accel->sig_symbols = syms_push_array_zero(arena, SYMS_SymbolID, accel->count);
3819
3820 SYMS_DwTagStubNode *child_n = children.first;
3821 for(SYMS_U64 idx = 0; idx < accel->count && child_n != 0; child_n = child_n->next)
3822 {
3824
3825 SYMS_MemInfo *out_mem_info = accel->mem_infos + idx;
3826 SYMS_USID *out_type_handle = accel->type_symbols + idx;
3827 SYMS_USID *out_full_handle = accel->full_symbols + idx;
3828 SYMS_SymbolID *out_sig_symbol = accel->sig_symbols + idx;
3829
3830 //- rjf: skip children we don't export in the members accelerator
3832 {
3833 accel->count -= 1;
3834 continue;
3835 }
3836 idx += 1;
3837
3838 //- rjf: get child attributes
3839 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, child_stub);
3840
3841 //- rjf: get info from attributes
3842 SYMS_String8 name = {0};
3844 SYMS_MemFlags flags = 0;
3848 SYMS_U32 offset = 0;
3849 SYMS_U32 virtual_offset = 0;
3850 for(SYMS_DwAttribNode *attrib_n = attribs.first;
3851 attrib_n != 0;
3852 attrib_n = attrib_n->next)
3853 {
3854 SYMS_DwAttrib *attrib = &attrib_n->attrib;
3856 attrib->form_kind,
3857 attrib->value_class,
3858 attrib->form_value);
3859
3860 switch(attrib->attrib_kind)
3861 {
3862 //- rjf: name
3864 {
3865 name = syms_dw_string_from_attrib_value(data, dbg, value);
3866 }break;
3867
3868 //- rjf: type
3870 {
3871 // TODO(rjf): This doesn't handle cross-unit references @dw_cross_unit
3872 type = syms_dw_sid_from_info_offset(value.v[0]);
3873 }break;
3874
3875 //- rjf: visibility
3877 {
3878 visibility = syms_dw_mem_visibility_from_access((SYMS_DwAccess)value.v[0]);
3879 }break;
3880
3881 //- rjf: virtuality
3883 {
3884 is_virtual = (value.v[0] == SYMS_DwVirtuality_Virtual ||
3885 value.v[0] == SYMS_DwVirtuality_PureVirtual);
3886 if(is_virtual)
3887 {
3888 flags |= SYMS_MemFlag_Virtual;
3889 }
3890 }break;
3891
3892 //- rjf: virtual table offset
3894 {
3895 switch(attrib->value_class)
3896 {
3897 // NOTE(rjf): I don't think these are ever reported as simple
3898 // offsets. There's not much we can do about that, even though
3899 // it'd be sufficient. Instead, we have to evaluate a DWARF
3900 // expression. But, I'm leaving this code here, as a desperate
3901 // wish to the stars that someday it'll be hit.
3903 {
3904 virtual_offset = value.v[0];
3905 }break;
3906
3907 //- rjf: best-first-guess at DWARF expression evaluation. this
3908 // won't be totally correct, since evaluation of an arbitrary
3909 // DWARF expression requires information about a running process,
3910 // but we can hit the common cases here.
3911 default:
3912 {
3915 void *exprloc_base = (void *)((SYMS_U8 *)debug_info_base + value.v[0]);
3917
3918 // TODO(allen): fill this in correctly
3919 SYMS_U64 text_base = 0;
3922 {
3923 // NOTE(rjf): These are reported in slots, but PDB reports in byte offsets,
3924 // so this maps to the same space as PDB.
3925 virtual_offset = loc.addr * unit->address_size;
3926 }
3928 }break;
3929 }
3930 }break;
3931
3932 //- rjf: external
3934 {
3936 }break;
3937
3938 //- rjf: bit offsets
3940 {
3941 switch(attrib->value_class)
3942 {
3944 {
3945 offset = value.v[0];
3946 }break;
3947 default:
3948 {
3949 // TODO(rjf): Must evaluate a DWARF expression in order to find out the byte offset. @dwarf_expr
3950 }break;
3951 }
3952 }break;
3954 {
3955 offset = value.v[0];
3956 }break;
3957
3958 }
3959 }
3960
3961 //- rjf: get tag-kind-specific data
3962 // TODO(rjf): offsets
3967 switch(child_stub->kind)
3968 {
3969 default: break;
3970
3972 {
3973 SYMS_DwTagStubFlags flags = child_stub->flags;
3976 inferred_type_symbol.sid = type;
3977
3978 if(child_stub->ref != 0)
3979 {
3983 flags |= child_ref_stub.flags;
3984 }
3986 {
3988 }
3989 }break;
3990
3992 {
3993 sig_symbol = child_stub->sid;
3994 kind = SYMS_MemKind_Method;
3995
3997 if(child_stub->ref != 0)
3998 {
3999 inferred_full_symbol.uid = unit->uid;
4002 {
4004 }
4005 }
4006
4007 //- rjf: check for constructor/destructor via best-guess string match
4008 {
4015 {
4016 real_child_name.str += 1;
4017 real_child_name.size -= 1;
4018 }
4020
4022 symbol_name = syms_string_trunc_symbol_heuristic(symbol_name);
4023 if(syms_string_match(symbol_name, real_child_name, 0))
4024 {
4026 {
4027 flags |= SYMS_MemFlag_Destructor;
4028 }
4029 else
4030 {
4031 flags |= SYMS_MemFlag_Constructor;
4032 }
4033 }
4034 }
4035
4036 }break;
4037
4039 {
4041 inferred_type_symbol.sid = type;
4043 }break;
4044
4049 {
4053 }break;
4054 }
4055
4056 //- rjf: fill
4057 out_mem_info->kind = kind;
4058 out_mem_info->name = name;
4059 out_mem_info->visibility = visibility;
4060 out_mem_info->flags = flags;
4061 out_mem_info->off = offset;
4062 out_mem_info->virtual_off = virtual_offset;
4066 }
4067 }
4069 return accel;
4070}
4071
4074{
4075 return mems->count;
4076}
4077
4081{
4082 SYMS_MemInfo result;
4083 syms_memzero_struct(&result);
4084 if(0 < n && n <= mems->count)
4085 {
4086 result = mems->mem_infos[n-1];
4087 }
4088 return result;
4089}
4090
4094 SYMS_U64 n)
4095{
4096 SYMS_USID result;
4097 syms_memzero_struct(&result);
4098 if(0 < n && n <= mems->count)
4099 {
4100 result = mems->type_symbols[n-1];
4101 }
4102 return result;
4103}
4104
4108{
4109 SYMS_SigInfo result;
4110 syms_memzero_struct(&result);
4111 if(0 < n && n <= mems->count)
4112 {
4114 result = syms_dw_sig_info_from_sid(arena, data, dbg, unit, sig_symbol);
4115 }
4116 return result;
4117}
4118
4122 SYMS_U64 n)
4123{
4124 SYMS_USID result;
4125 syms_memzero_struct(&result);
4126 if(0 < n && n <= mems->count)
4127 {
4128 result = mems->full_symbols[n-1];
4129 }
4130 return result;
4131}
4132
4136{
4140
4142 if(stub.sid != 0 && stub.kind == SYMS_DwTagKind_ENUMERATION_TYPE)
4143 {
4144 SYMS_DwTagStubList children = syms_dw_children_from_tag_stub(scratch.arena, data, dbg, unit, stub);
4145
4146 SYMS_U64 count = 0;
4147 for(SYMS_DwTagStubNode *child_n = children.first; child_n != 0; child_n = child_n->next)
4148 {
4151 {
4152 count += 1;
4153 }
4154 }
4155
4157 SYMS_U64 idx = 0;
4158 for(SYMS_DwTagStubNode *child_n = children.first; child_n != 0; child_n = child_n->next)
4159 {
4162 {
4163 SYMS_String8 name = {0};
4164 SYMS_U64 val = 0;
4165
4167 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(temp.arena, data, dbg, unit->language, unit->version, unit->address_size, child_stub);
4170
4171 for(SYMS_DwAttribNode *attrib_n = attribs.first;
4172 attrib_n != 0 && (!got_name || !got_val);
4173 attrib_n = attrib_n->next)
4174 {
4175 SYMS_DwAttrib *attrib = &attrib_n->attrib;
4177 attrib->form_kind, attrib->value_class, attrib->form_value);
4178 switch(attrib->attrib_kind)
4179 {
4181 {
4184 }break;
4186 {
4188 val = attrib_value.v[0];
4189 }break;
4190 }
4191 }
4192
4193 enum_members[idx].name = syms_push_string_copy(arena, name);
4194 enum_members[idx].val = val;
4195
4197 idx += 1;
4198 }
4199 }
4200
4201 array.count = count;
4202 array.enum_members = enum_members;
4203 }
4204
4206 return array;
4207}
4208
4211{
4212 SYMS_USID result = {0};
4213 result.uid = unit->uid;
4215 if(result.sid == 0)
4216 {
4219 }
4220 return result;
4221}
4222
4230
4232//~ rjf: Full Symbol Info Parsing
4233
4236{
4237 SYMS_String8 name = syms_str8_lit("");
4238 if(sid == SYMS_DWARF_VOID_TYPE_ID)
4239 {
4240 name = syms_str8_lit("void");
4241 }
4242 else
4243 {
4246 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, &stub);
4247 for(SYMS_DwAttribNode *n = attribs.first; n != 0; n = n->next)
4248 {
4249 SYMS_DwAttrib *attrib = &n->attrib;
4250 if(attrib->attrib_kind == kind)
4251 {
4253 attrib->form_kind,
4254 attrib->value_class,
4255 attrib->form_value);
4256 name = syms_dw_string_from_attrib_value(data, dbg, value);
4257 break;
4258 }
4259 }
4261 }
4262 return name;
4263}
4264
4267 SYMS_DwUnitAccel *unit,
4269{
4270 SYMS_String8 result = {0};
4271 for(SYMS_SymbolID id = sid; id != 0 && result.size == 0;)
4272 {
4273 result = syms_dw_attrib_string_from_sid__unstable(data, dbg, unit, kind, id);
4274 if(result.size == 0)
4275 {
4277 if(stub.ref != 0 && stub.flags & SYMS_DwTagStubFlag_HasSpecification)
4278 {
4279 id = stub.ref;
4280 }
4281 else if(stub.abstract_origin != 0)
4282 {
4283 id = stub.abstract_origin;
4284 }
4285 else
4286 {
4287 break;
4288 }
4289 }
4290 }
4291 return result;
4292}
4293
4296{
4299 result = syms_dw_symbol_kind_from_tag_stub(data, dbg, unit->resolve_params, &stub);
4300 return result;
4301}
4302
4310
4313{
4316
4318 if(stub.sid != 0)
4319 {
4321
4322 //- rjf: get attributes
4323 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, &stub);
4324
4325 //- rjf: define info from attributes
4326 SYMS_SymbolID type = 0;
4327 SYMS_UnitID type_uid = 0;
4329 SYMS_U64 size = 1;
4333 SYMS_U32 loc_line = 0;
4334 SYMS_U32 loc_column = 0;
4335 SYMS_USID containing_type = {0};
4336
4337 //- rjf: loop through DWARF attributes and fill info
4338 for(SYMS_DwAttribNode *attrib_n = attribs.first;
4339 attrib_n != 0;
4340 attrib_n = attrib_n->next)
4341 {
4342 SYMS_DwAttrib *attrib = &attrib_n->attrib;
4344 switch(attrib->attrib_kind)
4345 {
4346 //- rjf: type references
4348 {
4349 type = syms_dw_sid_from_info_offset(value.v[0]);
4350 // TODO(rjf): This doesn't handle cross-unit references @dw_cross_unit
4351 type_uid = unit->uid;
4352 }break;
4353
4354 //- rjf: containing types (used for member-pointers)
4356 {
4357 // TODO(rjf): This doesn't handle cross-unit references @dw_cross_unit
4358 containing_type.sid = syms_dw_sid_from_info_offset(value.v[0]);
4359 containing_type.uid = unit->uid;
4360 }break;
4361
4362 //- rjf: sizes
4365 read_size:;
4366 {
4367 size = value.v[0];
4368 }break;
4370 {
4372 size = (value.v[0] + 7)/8;
4373 }break;
4374
4375 //- rjf: misc enums
4377 {
4378 encoding = (SYMS_DwAttribTypeEncoding)value.v[0];
4379 }break;
4381 {
4382 call_convention = (SYMS_DwCallingConvention)value.v[0];
4383 }break;
4384
4385 //- rjf: loc
4387 case SYMS_DwAttribKind_DECL_LINE: {loc_line = (SYMS_U32)value.v[0]; }break;
4388 case SYMS_DwAttribKind_DECL_COLUMN: {loc_column = (SYMS_U32)value.v[0]; }break;
4389
4390 default: break;
4391 }
4392 }
4393
4394 //- rjf: fill
4395 info.kind = syms_dw_type_kind_from_tag_encoding_size(stub.kind, encoding, size);
4397 info.direct_type.uid = type_uid;
4398 info.direct_type.sid = type;
4400 info.reported_size = size;
4401 info.src_coord.file_id = loc_file;
4402 info.src_coord.line = loc_line;
4403 info.src_coord.col = loc_column;
4404 switch (info.kind){
4405 case SYMS_TypeKind_Proc:
4406 {
4408 }break;
4410 {
4411 info.containing_type = containing_type;
4412 }break;
4413 }
4414
4415 //- rjf: void type direct_type
4416 if(sid != void_id && type == 0 &&
4417 (info.mods != 0 ||
4420 {
4421 info.direct_type.uid = unit->uid;
4422 info.direct_type.sid = void_id;
4423 }
4424
4425 //- rjf: type kind fill overrides
4426 if(sid == void_id)
4427 {
4428 info.kind = SYMS_TypeKind_Void;
4430 info.reported_size = 0;
4431 }
4432
4433 //- rjf: size fill overrides
4434 {
4435 if(info.kind == SYMS_TypeKind_Ptr)
4436 {
4437 info.reported_size = unit->address_size;
4439 }
4440 else if(info.kind == SYMS_TypeKind_MemberPtr)
4441 {
4443 info.reported_size = 0;
4444 if(type != 0)
4445 {
4447
4448 // NOTE(rjf): It looks like DWARF doesn't export size information for
4449 // member pointers, despite the fact that they are not the same size
4450 // as regular pointers. In experimentation, we've found that with
4451 // DWARF-producing builds by compilers, method-pointers look to be
4452 // 16 bytes (not 8, due to multiple inheritance), and regular member
4453 // pointers look like they're 8 bytes (despite their equivalent being
4454 // 4 bytes in PDB). These aren't necessarily what they are, but this
4455 // is what their layout in structs would suggest. So, until we find a
4456 // better way to do this, we're just going to assume that if we're
4457 // pointing at a member function, we're 2 * ptr sized, and if we're
4458 // not, then we're ptr sized.
4460 {
4461 info.reported_size = unit->address_size * 2;
4462 }
4463 else
4464 {
4465 info.reported_size = unit->address_size;
4466 }
4467 }
4468 }
4469 }
4470
4471 //- rjf: for array types: override fill from children
4472 if(info.kind == SYMS_TypeKind_Array)
4473 {
4474 SYMS_DwTagStubList children = syms_dw_children_from_tag_stub(scratch.arena, data, dbg, unit, stub);
4475 for(SYMS_DwTagStubNode *child_n = children.first; child_n; child_n = child_n->next)
4476 {
4477 SYMS_DwTagStub *child = &child_n->stub;
4479 {
4481
4483 child_attrib_n != 0;
4485 {
4487 if(child_attrib->attrib_kind == SYMS_DwAttribKind_ARR_COUNT)
4488 {
4490 child_attrib->form_kind,
4491 child_attrib->value_class,
4492 child_attrib->form_value);
4493 info.reported_size = value.v[0];
4495 break;
4496 }
4497 }
4498 break;
4499 }
4500 }
4501 }
4502 }
4503
4505 return info;
4506}
4507
4510{
4512 SYMS_ConstInfo info;
4513 syms_memzero_struct(&info);
4514
4516 if(stub.sid != 0)
4517 {
4518 //- rjf: get attributes
4519 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, &stub);
4520
4521 //- rjf: define info from attributes
4522 SYMS_U64 const_value = 0;
4523
4524 //- rjf: loop through DWARF attributes and fill info
4525 for(SYMS_DwAttribNode *attrib_n = attribs.first;
4526 attrib_n != 0;
4527 attrib_n = attrib_n->next)
4528 {
4529 SYMS_DwAttrib *attrib = &attrib_n->attrib;
4531 switch(attrib->attrib_kind)
4532 {
4533 //- rjf: const values
4535 {
4536 switch(attrib->value_class)
4537 {
4539 {
4540 const_value = value.v[0];
4541 }break;
4542 default: /* TODO(rjf): */ break;
4543 }
4544 }break;
4545
4546 default: break;
4547 }
4548 }
4549
4550 //- rjf: fill
4552 info.val = const_value;
4553 }
4554
4556 return info;
4557}
4558
4561{
4563 SYMS_USID result;
4564 syms_memzero_struct(&result);
4566 if(stub.sid != 0)
4567 {
4568 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, &stub);
4569 result.uid = unit->uid;
4571 for(SYMS_DwAttribNode *attrib_n = attribs.first;
4572 attrib_n != 0;
4573 attrib_n = attrib_n->next)
4574 {
4575 SYMS_DwAttrib *attrib = &attrib_n->attrib;
4577 if(attrib->attrib_kind == SYMS_DwAttribKind_TYPE)
4578 {
4579 // TODO(rjf): This does not handle cross-unit references @dw_cross_unit
4580 result.sid = syms_dw_sid_from_info_offset(value.v[0]);
4581 result.uid = unit->uid;
4582 break;
4583 }
4584 }
4585 }
4587 return result;
4588}
4589
4592{
4593 SYMS_U64 result = 0;
4596 if(stub.sid != 0)
4597 {
4598 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, &stub);
4599
4601 for(SYMS_DwAttribNode *attrib_n = attribs.first;
4602 attrib_n != 0;
4603 attrib_n = attrib_n->next)
4604 {
4605 SYMS_DwAttrib *attrib = &attrib_n->attrib;
4607 location_attrib = attrib;
4608 break;
4609 }
4610 }
4611
4612 if(location_attrib != 0)
4613 {
4615 location_attrib->form_kind,
4616 location_attrib->value_class,
4617 location_attrib->form_value);
4618
4619 switch (location_attrib->value_class){
4621 {
4622 result = value.v[0];
4623 }break;
4624
4625 default:
4626 {
4629 void *exprloc_base = ((SYMS_U8*)debug_info_base + value.v[0]);
4631
4632 // TODO(allen): fill this in correctly
4633 SYMS_U64 text_base = 0;
4636 result = loc.addr;
4637 }
4638
4640 }break;
4641 }
4642 }
4643 }
4645 return(result);
4646}
4647
4650{
4655 SYMS_DwTagStubList children = syms_dw_children_from_tag_stub(scratch.arena, data, dbg, unit, stub);
4656 for(SYMS_DwTagStubNode *n = children.first; n != 0; n = n->next)
4657 {
4658 SYMS_B32 matches = 0;
4659 for(SYMS_U64 kind_idx = 0; kind_idx < count; kind_idx += 1)
4660 {
4661 if(n->stub.kind == kinds[kind_idx])
4662 {
4663 matches = 1;
4664 break;
4665 }
4666 }
4667 if(matches)
4668 {
4670 node->id = n->stub.sid;
4671 SYMS_QueuePush(list.first, list.last, node);
4672 list.count += 1;
4673 }
4674 }
4676 return list;
4677}
4678
4679//- rjf: variable locations
4680
4683{
4684 SYMS_Location result = {0};
4686
4688 if(stub.sid != 0)
4689 {
4690 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, &stub);
4691 for(SYMS_DwAttribNode *n = attribs.first; n != 0; n = n->next)
4692 {
4693 SYMS_DwAttrib *attrib = &n->attrib;
4694 if(attrib->attrib_kind == loc_attrib &&
4696 {
4698 attrib->form_kind,
4699 attrib->value_class,
4700 attrib->form_value);
4704 break;
4705 }
4706 }
4707 }
4708
4709 // TODO(rjf): once SYMS_Location has changed accordingly (returns a string
4710 // instead of an op-list, wire up `location` to `result`)
4711
4713 return result;
4714}
4715
4719{
4720 SYMS_LocRangeArray result = {0};
4722
4723 // rjf: get location range list from sid, if applicable
4724 SYMS_LocRangeList list = {0};
4726 if(stub.sid != 0)
4727 {
4728 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, &stub);
4729 for(SYMS_DwAttribNode *n = attribs.first; n != 0; n = n->next)
4730 {
4731 SYMS_DwAttrib *attrib = &n->attrib;
4732 if(attrib->attrib_kind == loc_attrib &&
4735 {
4737 attrib->form_kind,
4738 attrib->value_class,
4739 attrib->form_value);
4741 switch(location_value.section)
4742 {
4743 // NOTE(rjf): .debug_loclists is only available in DWARF V5, so we can use that to
4744 // determine which parsing path to use.
4746 {
4748 }break;
4749
4750 // NOTE(rjf): .debug_loclists is only available in DWARF V4 and earlier.
4752 {
4754 }break;
4755 }
4756 break;
4757 }
4758 }
4759 }
4760
4761 // rjf: convert list => array
4762 if(list.count != 0)
4763 {
4764 result.count = list.count;
4765 result.loc_ranges = syms_push_array_zero(arena, SYMS_LocRange, result.count);
4766 SYMS_U64 idx = 0;
4767 for(SYMS_LocRangeNode *n = list.first; n != 0; n = n->next, idx += 1)
4768 {
4769 result.loc_ranges[idx] = n->loc_range;
4770 }
4771 }
4772
4774 return result;
4775}
4776
4779 SYMS_DwUnitAccel *unit, SYMS_LocID loc_id)
4780{
4781 SYMS_Location result = {0};
4782 switch(unit->version)
4783 {
4785 case SYMS_DwVersion_V4:{syms_dw_v4_location_from_loc_id(arena, data, dbg, loc_id);}break;
4786 }
4787 return result;
4788}
4789
4790//- rjf: location information helpers
4791
4794{
4796 switch(proc_loc)
4797 {
4800 }
4801 return attrib;
4802}
4803
4809
4816
4824
4828{
4830 SYMS_LocRangeArray ranges = syms_dw_location_ranges_from_sid(arena, data, dbg, unit, sid, attrib_kind);
4831 return ranges;
4832}
4833
4834//- rjf: files
4835
4838{
4839 return id - 1;
4840}
4841
4844{
4845 return idx + 1;
4846}
4847
4850{
4851 SYMS_String8 result = {0};
4852
4853 //- rjf: get comp root
4854 SYMS_DwCompRoot *root = syms_dw_comp_root_from_uid(unit_set, uid);
4855
4856 //- rjf: get .debug_line file struct for this file ID
4858 SYMS_DwLineFile file = {0};
4860 if(0 <= file_idx && file_idx < root->file_table.count)
4861 {
4862 file = root->file_table.v[file_idx];
4864 }
4865
4866 //- rjf: get directory string for this file
4867 SYMS_String8 dir = {0};
4868 if(good_file && 0 <= file.dir_idx && file.dir_idx < root->dir_table.count)
4869 {
4870 dir = root->dir_table.strings[file.dir_idx];
4871 }
4872
4873 //- rjf: build final string
4874 result = syms_dw_path_from_dir_and_filename(arena, dir, file.file_name);
4875
4876 return result;
4877}
4878
4879//- rjf: procedures
4880
4884{
4888
4889 //- rjf: id => stub
4891
4892 //- rjf: get range list
4893 if(stub.sid != 0)
4894 {
4895 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, &stub);
4896
4897 SYMS_U64 low_pc = 0;
4898 SYMS_U64 high_pc = 0;
4900 SYMS_DwAttribValue ranges_attrib_value = {SYMS_DwSectionKind_Null};
4901
4902 for(SYMS_DwAttribNode *attrib_n = attribs.first;
4903 attrib_n != 0;
4904 attrib_n = attrib_n->next)
4905 {
4906 SYMS_DwAttrib *attrib = &attrib_n->attrib;
4908
4910 {
4911 ranges_attrib_value = value;
4912 }
4913 else if(attrib->attrib_kind == SYMS_DwAttribKind_LOW_PC)
4914 {
4915 low_pc = value.v[0];
4916 }
4917 else if(attrib->attrib_kind == SYMS_DwAttribKind_HIGH_PC)
4918 {
4919 high_pc = value.v[0];
4921 }
4922 }
4923
4925 {
4926 high_pc = low_pc + high_pc;
4927 }
4929 unit->address_size,
4930 unit->base_addr,
4931 unit->addrs_base,
4932 low_pc,
4933 high_pc,
4934 ranges_attrib_value);
4935 }
4936
4937 SYMS_U64RangeArray result;
4938 syms_memzero_struct(&result);
4939 result = syms_u64_range_array_from_list(arena, &list);
4941 return result;
4942}
4943
4947{
4949
4956
4957 //- rjf: get info from id
4959 if(stub.sid != 0)
4960 {
4961 SYMS_DwAttribList attribs = syms_dw_attrib_list_from_stub(scratch.arena, data, dbg, unit->language, unit->version, unit->address_size, &stub);
4962
4963 //- rjf: grab return type
4964 for(SYMS_DwAttribNode *attrib_n = attribs.first;
4965 attrib_n != 0;
4966 attrib_n = attrib_n->next)
4967 {
4968 SYMS_DwAttrib *attrib = &attrib_n->attrib;
4970 if(attrib->attrib_kind == SYMS_DwAttribKind_TYPE)
4971 {
4973 break;
4974 }
4975 }
4976
4977 //- rjf: figure out if this is a member function
4979 SYMS_DwTagStubFlags flags = stub.flags | ref_stub.flags;
4980
4981 //- rjf: grab children
4982 SYMS_DwTagStubList children = syms_dw_children_from_tag_stub(scratch.arena, data, dbg, unit, stub);
4983
4984 //- rjf: grab param types
4985 int child_idx = 0;
4986 for(SYMS_DwTagStubNode *child_n = children.first; child_n != 0; child_n = child_n->next, child_idx += 1)
4987 {
4988 SYMS_DwTagStub *child = &child_n->stub;
4990 {
4994 child_attrib_n != 0;
4996 {
4997 SYMS_DwAttrib *attrib = &child_attrib_n->attrib;
4998 if(attrib->attrib_kind == SYMS_DwAttribKind_TYPE)
4999 {
5002 break;
5003 }
5004 }
5005
5006 if(child_idx == 0 && flags & SYMS_DwTagStubFlag_HasObjectPointerArg)
5007 {
5009 }
5010 else
5011 {
5013 }
5014 }
5015 }
5016 }
5017
5018 //- rjf: build/fill result
5019 SYMS_SigInfo result;
5020 syms_memzero_struct(&result);
5021 result.uid = unit->uid;
5023 result.return_type_id = return_type;
5024 result.this_type_id = this_ptr_type;
5025
5027 return result;
5028}
5029
5032 SYMS_SymbolID sid){
5033 SYMS_UnitIDAndSig result = {unit->uid, {sid}};
5034 return result;
5035}
5036
5039 SYMS_SymbolID id = {handle.v};
5040 return syms_dw_sig_info_from_sid(arena, data, dbg, unit, id);
5041}
5042
5064
5065//- rjf: line info
5066
5067SYMS_API void
5069 state->address = 0;
5070 state->op_index = 0;
5071 state->file_index = 1;
5072 state->line = 1;
5073 state->column = 0;
5074 state->is_stmt = default_is_stmt;
5075 state->basic_block = syms_false;
5076 state->prologue_end = syms_false;
5077 state->epilogue_begin = syms_false;
5078 state->isa = 0;
5079 state->discriminator = 0;
5080}
5081
5082SYMS_API void
5084 SYMS_U64 min_inst_len, SYMS_U64 max_ops_for_inst){
5085 SYMS_U64 op_index = state->op_index + advance;
5086 state->address += min_inst_len*(op_index/max_ops_for_inst);
5087 state->op_index = op_index % max_ops_for_inst;
5088}
5089
5092{
5094 SYMS_QueuePush(parsed_tbl->first_seq, parsed_tbl->last_seq, new_seq);
5095 parsed_tbl->seq_count += 1;
5096 SYMS_Log("<new sequence>\n");
5097 return new_seq;
5098}
5099
5102{
5103 SYMS_DwLineNode *n = 0;
5104 if(vm_state->busted_seq == 0)
5105 {
5107 if(seq == 0 || start_of_sequence)
5108 {
5109 if(seq && seq->count == 1)
5110 {
5111 SYMS_Log("ERROR! do not emit sequences with only one line...\n");
5112 }
5113 seq = syms_dw_push_line_seq(arena, tbl);
5114 }
5115
5117 SYMS_QueuePush(seq->first, seq->last, n);
5118 seq->count += 1;
5120 n->line.src_coord.line = vm_state->line;
5121 n->line.src_coord.col = vm_state->column;
5122 n->line.voff = vm_state->address;
5123 SYMS_Log(" line: [%i] %i:%i => %llx\n",
5124 vm_state->file_index,vm_state->line, vm_state->column, vm_state->address);
5125 }
5126 return n;
5127}
5128
5131{
5133
5135 void *base = syms_dw_sec_base_from_dbg(data, dbg, SYMS_DwSectionKind_Line);
5139
5141 read_off += syms_dw_read_line_vm_header(arena, base, line_info_range, read_off, data, mode, dbg, root, &vm_header);
5142
5143 //- rjf: prep state for VM
5146 syms_dw_line_vm_reset(&vm_state, vm_header.default_is_stmt);
5147
5148 //- rjf: VM loop; build output list
5149 SYMS_DwLineTableParseResult result = {0};
5150 SYMS_B32 end_of_seq = 0;
5151 SYMS_B32 error = syms_false;
5152 for (;!error && read_off < vm_header.unit_opl;){
5153 //- rjf: parse opcode
5154 SYMS_U8 opcode = 0;
5156
5157 //- rjf: do opcode action
5158 switch (opcode){
5159 default:
5160 {
5161 //- rjf: special opcode case
5162 if(opcode >= vm_header.opcode_base)
5163 {
5167 // TODO(allen): can we just call dw_advance_line_vm_state_pc
5168 SYMS_U64 addr_inc = vm_header.min_inst_len * ((vm_state.op_index+op_advance) / vm_header.max_ops_for_inst);
5169 vm_state.address += addr_inc;
5170 vm_state.op_index = (vm_state.op_index + op_advance) % vm_header.max_ops_for_inst;
5171 vm_state.line = (SYMS_U32)((SYMS_S32)vm_state.line + line_inc);
5172 vm_state.basic_block = syms_false;
5173 vm_state.prologue_end = syms_false;
5174 vm_state.epilogue_begin = syms_false;
5175 vm_state.discriminator = 0;
5176
5177 SYMS_Log("[special opcode] inc line by %i, inc addr by %i\n", line_inc, (int)addr_inc);
5178 syms_dw_push_line(arena, &result, &vm_state, end_of_seq);
5179 end_of_seq = 0;
5180
5181#if 0
5182 // NOTE(rjf): DWARF has dummy lines at the end of groups of line ranges, where we'd like
5183 // to break line info into sequences.
5184 if(vm_state.line == 0)
5185 {
5186 end_of_seq = 1;
5187 }
5188#endif
5189 }
5190 //- NOTE(nick): Skipping unknown opcode. This is a valid case and
5191 // it works because compiler stores operand lengths that we can read
5192 // to skip unknown opcode
5193 else{
5194 if (opcode > 0 && opcode <= vm_header.num_opcode_lens){
5195 SYMS_U8 num_operands = vm_header.opcode_lens[opcode - 1];
5196 for (SYMS_U8 i = 0; i < num_operands; i += 1){
5197 SYMS_U64 operand = 0;
5199 }
5200 }
5201 else{
5202 error = syms_true;
5203 goto exit;
5204 }
5205 }
5206 }break;
5207
5208 //- NOTE(nick): standard opcodes
5209
5211 {
5212 SYMS_Log("copy\n");
5213 syms_dw_push_line(arena, &result, &vm_state, end_of_seq);
5214 end_of_seq = 0;
5215 vm_state.discriminator = 0;
5216 vm_state.basic_block = syms_false;
5217 vm_state.prologue_end = syms_false;
5218 vm_state.epilogue_begin = syms_false;
5219 }break;
5220
5222 {
5223 SYMS_U64 advance = 0;
5225 syms_dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst);
5226 SYMS_Log("advance pc by %i, now %" SYMS_PRIx64 "\n", (int)advance, vm_state.address);
5227 }break;
5228
5230 {
5231 SYMS_S64 s = 0;
5233 vm_state.line += s;
5234 SYMS_Log("advance line by %i\n", (int)s);
5235 }break;
5236
5238 {
5239 SYMS_U64 file_index = 0;
5241 vm_state.file_index = file_index;
5242 SYMS_Log("set file to %i\n", (int)file_index);
5243 }break;
5244
5246 {
5247 SYMS_U64 column = 0;
5249 vm_state.column = column;
5250 SYMS_Log("set column to %i\n", (int)column);
5251 }break;
5252
5254 {
5255 vm_state.is_stmt = !vm_state.is_stmt;
5256 SYMS_Log("negate is_stmt (now is %i)\n", (int)vm_state.is_stmt);
5257 }break;
5258
5260 {
5261 vm_state.basic_block = syms_true;
5262 SYMS_Log("set basic_block to true\n");
5263 }break;
5264
5266 {
5267 SYMS_U64 advance = (0xffu - vm_header.opcode_base)/vm_header.line_range;
5268 syms_dw_line_vm_advance(&vm_state, advance, vm_header.min_inst_len, vm_header.max_ops_for_inst);
5269 SYMS_Log("const add pc with %i\n", (int)advance);
5270 }break;
5271
5273 {
5274 SYMS_U16 operand = 0;
5276 vm_state.address += operand;
5277 vm_state.op_index = 0;
5278 SYMS_Log("fixed add pc with %i\n", (int)operand);
5279 }break;
5280
5282 {
5283 vm_state.prologue_end = syms_true;
5284 SYMS_Log("set prologue end\n");
5285 }break;
5286
5288 {
5289 vm_state.epilogue_begin = syms_true;
5290 SYMS_Log("set epilogue begin\n");
5291 }break;
5292
5294 {
5295 SYMS_U64 v = 0;
5297 vm_state.isa = v;
5298 SYMS_Log("set isa to %i\n", (int)v);
5299 }break;
5300
5301 //- NOTE(nick): extended opcodes
5303 {
5304 SYMS_U64 length = 0;
5309
5310 switch (extended_opcode){
5312 {
5313 vm_state.end_sequence = syms_true;
5314 syms_dw_push_line(arena, &result, &vm_state, 0);
5315 SYMS_Log("<end sequence>\n");
5316 syms_dw_line_vm_reset(&vm_state, vm_header.default_is_stmt);
5317 end_of_seq = 1;
5318 }break;
5319
5321 {
5322 SYMS_U64 address = 0;
5324 vm_state.address = address;
5325 vm_state.op_index = 0;
5326 vm_state.busted_seq = !(dbg->acceptable_vrange.min <= address && address < dbg->acceptable_vrange.max);
5327 SYMS_Log("set address to %" SYMS_PRIx64 "\n", address);
5328 }break;
5329
5331 {
5333 SYMS_U64 dir_index = 0;
5334 SYMS_U64 modify_time = 0;
5335 SYMS_U64 file_size = 0;
5336 read_off += file_name.size + 1;
5340
5341 // TODO(rjf): Not fully implemented. By the DWARF V4 spec, the above is
5342 // all that needs to be parsed, but the rest of the work that needs to
5343 // happen here---allowing this file to be used by further opcodes---is
5344 // not implemented.
5345 //
5346 // See the DWARF V4 spec (June 10, 2010), page 122.
5347 error = syms_true;
5348 SYMS_Log("UNHANDLED DEFINE FILE!!!\n");
5349 }break;
5350
5352 {
5353 SYMS_U64 v = 0;
5355 vm_state.discriminator = v;
5356 SYMS_Log("set discriminator to %" SYMS_PRIx64 "\n", v);
5357 }break;
5358
5359 default: break;
5360 }
5361
5362 SYMS_U64 num_skip = read_off - (start_off + length);
5363 read_off += num_skip;
5364 if (syms_based_range_ptr(base, line_info_range, read_off) == 0 ||
5365 start_off + length > read_off){
5366 error = syms_true;
5367 }
5368
5369 }break;
5370 }
5371 }
5372 exit:;
5373
5375
5376 return(result);
5377}
5378
5381{
5383 SYMS_DwCompRoot *root = syms_dw_comp_root_from_uid(unit_set, uid);
5385 SYMS_LineParseOut result = {0};
5386 {
5387 //- rjf: calculate # of lines we have
5388 SYMS_U64 line_count = 0;
5389 SYMS_U64 seq_count = 0;
5390 for(SYMS_DwLineSeqNode *seq = parsed_tbl.first_seq; seq != 0; seq = seq->next)
5391 {
5392 if(seq->count > 1)
5393 {
5394 line_count += seq->count;
5395 seq_count += 1;
5396 }
5397 }
5398
5399 //- rjf: set up arrays
5400 SYMS_U64 *sequence_index_array = syms_push_array_zero(arena, SYMS_U64, parsed_tbl.seq_count + 1);
5401 SYMS_Line *line_array = syms_push_array_zero(arena, SYMS_Line, line_count);
5402
5403 //- rjf: fill arrays
5404 SYMS_U64 line_idx = 0;
5405 SYMS_U64 seq_idx = 0;
5406 for (SYMS_DwLineSeqNode *seq = parsed_tbl.first_seq;
5407 seq != 0;
5408 seq = seq->next, seq_idx += 1){
5409 sequence_index_array[seq_idx] = line_idx;
5410 for (SYMS_DwLineNode *line = seq->first;
5411 line != 0;
5412 line = line->next, line_idx += 1){
5413 line_array[line_idx] = line->line;
5414 }
5415 }
5416 sequence_index_array[seq_idx] = line_idx;
5417
5418 //- fill result
5419 result.line_table.sequence_count = parsed_tbl.seq_count;
5420 result.line_table.sequence_index_array = sequence_index_array;
5421 result.line_table.line_count = line_count;
5422 result.line_table.line_array = line_array;
5423 }
5425 return result;
5426}
5427
5430{
5432
5434 SYMS_U64 line_off_start = line_off;
5436 {
5439 SYMS_DwAttribValue form_value;
5440 syms_memzero_struct(&form_value);
5441 line_off += syms_dw_based_range_read_attrib_form_value(line_base, line_rng, line_off, mode, address_size, form_kind, 0, &form_value);
5442 switch (lnct)
5443 {
5444 case SYMS_DwLNCT_PATH:
5445 {
5447 form_kind == SYMS_DwFormKind_STRP || form_kind == SYMS_DwFormKind_STRP_SUP ||
5448 form_kind == SYMS_DwFormKind_STRX || form_kind == SYMS_DwFormKind_STRX1 ||
5449 form_kind == SYMS_DwFormKind_STRX2 || form_kind == SYMS_DwFormKind_STRX3 ||
5450 form_kind == SYMS_DwFormKind_STRX4);
5451 SYMS_DwAttribValue attrib_value = syms_dw_attrib_value_from_form_value(data, dbg, resolve_params, form_kind, SYMS_DwAttribClass_STRING, form_value);
5453 } break;
5454
5456 {
5458 form_kind == SYMS_DwFormKind_UDATA);
5459 SYMS_DwAttribValue attrib_value = syms_dw_attrib_value_from_form_value(data, dbg, resolve_params, form_kind, SYMS_DwAttribClass_BLOCK, form_value);
5460 line_file_out->dir_idx = attrib_value.v[0];
5461 } break;
5462
5464 {
5466 form_kind == SYMS_DwFormKind_DATA8 || form_kind == SYMS_DwFormKind_BLOCK);
5467 SYMS_DwAttribValue attrib_value = syms_dw_attrib_value_from_form_value( data, dbg, resolve_params, form_kind, SYMS_DwAttribClass_CONST, form_value);
5468 line_file_out->modify_time = attrib_value.v[0];
5469 } break;
5470
5471 case SYMS_DwLNCT_SIZE:
5472 {
5474 form_kind == SYMS_DwFormKind_DATA2 || form_kind == SYMS_DwFormKind_DATA4 ||
5475 form_kind == SYMS_DwFormKind_DATA8);
5476 SYMS_DwAttribValue attrib_value = syms_dw_attrib_value_from_form_value(data, dbg, resolve_params, form_kind, SYMS_DwAttribClass_BLOCK, form_value);
5477 line_file_out->file_size = attrib_value.v[0];
5478 } break;
5479
5480 case SYMS_DwLNCT_MD5:
5481 {
5483 SYMS_DwAttribValue attrib_value = syms_dw_attrib_value_from_form_value(data, dbg, resolve_params, form_kind, SYMS_DwAttribClass_BLOCK, form_value);
5484 line_file_out->md5_digest[0] = attrib_value.v[0];
5485 line_file_out->md5_digest[1] = attrib_value.v[1];
5486 } break;
5487
5488 default:
5489 {
5491 } break;
5492 }
5493 }
5494 SYMS_U64 result = line_off - line_off_start;
5495 return result;
5496}
5497
5500{
5501 SYMS_U64 line_off_start = line_off;
5502
5504
5505 //- rjf: parse unit length
5506 header_out->unit_length = 0;
5507 {
5508 line_off += syms_dw_based_range_read_length(line_base, line_rng, line_off, &header_out->unit_length);
5509 }
5510
5511 header_out->unit_opl = line_off + header_out->unit_length;
5512
5513 //- rjf: parse version and header length
5514 line_off += syms_based_range_read_struct(line_base, line_rng, line_off, &header_out->version);
5515
5516 if (header_out->version == SYMS_DwVersion_V5) {
5517 line_off += syms_based_range_read_struct(line_base, line_rng, line_off, &header_out->address_size);
5518 line_off += syms_based_range_read_struct(line_base, line_rng, line_off, &header_out->segment_selector_size);
5519 }
5520
5521 {
5523 line_off += syms_based_range_read(line_base, line_rng, line_off, off_size, &header_out->header_length);
5524 }
5525
5526 //- rjf: calculate program offset
5527 header_out->program_off = line_off + header_out->header_length;
5528
5529 //- rjf: parse minimum instruction length
5530 {
5531 line_off += syms_based_range_read_struct(line_base, line_rng, line_off, &header_out->min_inst_len);
5532 }
5533
5534 //- rjf: parse max ops for instruction
5535 switch (header_out->version)
5536 {
5537 case SYMS_DwVersion_V5:
5538 case SYMS_DwVersion_V4:
5539 {
5540 line_off += syms_based_range_read_struct(line_base, line_rng, line_off, &header_out->max_ops_for_inst);
5541 SYMS_ASSERT_PARANOID(header_out->max_ops_for_inst > 0);
5542 } break;
5543 case SYMS_DwVersion_V3:
5544 case SYMS_DwVersion_V2:
5545 case SYMS_DwVersion_V1:
5546 {
5547 header_out->max_ops_for_inst = 1;
5548 } break;
5549 default: break;
5550 }
5551
5552 //- rjf: parse rest of program info
5553 syms_based_range_read_struct(line_base, line_rng, line_off + 0 * sizeof(SYMS_U8), &header_out->default_is_stmt);
5554 syms_based_range_read_struct(line_base, line_rng, line_off + 1 * sizeof(SYMS_U8), &header_out->line_base);
5555 syms_based_range_read_struct(line_base, line_rng, line_off + 2 * sizeof(SYMS_U8), &header_out->line_range);
5556 syms_based_range_read_struct(line_base, line_rng, line_off + 3 * sizeof(SYMS_U8), &header_out->opcode_base);
5557 line_off += 4 * sizeof(SYMS_U8);
5558 SYMS_ASSERT_PARANOID(header_out->opcode_base != 0 && header_out->opcode_base > 0);
5559
5560 //- rjf: calculate opcode length array
5561 header_out->num_opcode_lens = header_out->opcode_base - 1u;
5562 header_out->opcode_lens = (SYMS_U8 *)syms_based_range_ptr(line_base, line_rng, line_off);
5563 line_off += header_out->num_opcode_lens * sizeof(SYMS_U8);
5564
5565 if (header_out->version == SYMS_DwVersion_V5) {
5566 //- parse directory names
5568 line_off += syms_based_range_read_struct(line_base, line_rng, line_off, &directory_entry_format_count);
5573 {
5575 line_off += syms_based_range_read_uleb128(line_base, line_rng, line_off, &content_type_code);
5576 line_off += syms_based_range_read_uleb128(line_base, line_rng, line_off, &form_code);
5578 }
5580 line_off += syms_based_range_read_uleb128(line_base, line_rng, line_off, &directories_count);
5581 header_out->dir_table.count = directories_count;
5582 header_out->dir_table.strings = syms_push_array(arena, SYMS_String8, header_out->dir_table.count);
5583 for (SYMS_U64 dir_idx = 0; dir_idx < directories_count; ++dir_idx)
5584 {
5586 line_off += syms_dw_read_line_file(line_base,
5587 line_rng,
5588 line_off,
5589 mode,
5590 dbg,
5591 data,
5592 unit,
5596 &line_file);
5597 // imperically directory format defines just names, but format is structured so it can export md5, time stamp for directories
5598
5599 SYMS_String8 file_name = syms_push_string_copy(arena, line_file.file_name);
5600 header_out->dir_table.strings[dir_idx] = file_name;
5601 }
5602 //- parse file table
5604 line_off += syms_based_range_read_struct(line_base, line_rng, line_off, &file_name_entry_format_count);
5607 {
5609 line_off += syms_based_range_read_uleb128(line_base, line_rng, line_off, &content_type_code);
5610 line_off += syms_based_range_read_uleb128(line_base, line_rng, line_off, &form_code);
5612 }
5614 line_off += syms_based_range_read_uleb128(line_base, line_rng, line_off, &file_names_count);
5615 header_out->file_table.count = file_names_count;
5616 header_out->file_table.v = syms_push_array(arena, SYMS_DwLineFile, header_out->file_table.count);
5617 //SYMS_ASSERT_IMPLIES(file_name_entry_format_count == 0, file_names_count == 0);
5619 {
5620 line_off += syms_dw_read_line_file(line_base,
5621 line_rng,
5622 line_off,
5623 mode,
5624 dbg,
5625 data,
5626 unit,
5630 &header_out->file_table.v[file_idx]);
5631 }
5632 }
5633 else
5634 {
5637
5639 for (;;)
5640 {
5641 SYMS_String8 dir = syms_based_range_read_string(line_base, line_rng, line_off);
5642 line_off += dir.size + 1;
5643 if (dir.size == 0)
5644 {
5645 break;
5646 }
5648 }
5649
5652
5653 //- rjf: push 0-index file (compile file)
5654 {
5656 syms_memzero_struct(node);
5657 node->file.file_name = unit->name;
5658 SYMS_QueuePush(file_list.first, file_list.last, node);
5659 file_list.node_count += 1;
5660 }
5661
5662 for (;;)
5663 {
5664 SYMS_String8 file_name = syms_based_range_read_string(line_base, line_rng, line_off);
5665 SYMS_U64 dir_index = 0;
5666 SYMS_U64 modify_time = 0;
5667 SYMS_U64 file_size = 0;
5668 line_off += file_name.size + 1;
5669 if (file_name.size == 0)
5670 {
5671 break;
5672 }
5673 line_off += syms_based_range_read_uleb128(line_base, line_rng, line_off, &dir_index);
5674 line_off += syms_based_range_read_uleb128(line_base, line_rng, line_off, &modify_time);
5675 line_off += syms_based_range_read_uleb128(line_base, line_rng, line_off, &file_size);
5676
5678 node->file.file_name = file_name;
5679 node->file.dir_idx = dir_index;
5680 node->file.modify_time = modify_time;
5681 node->file.file_size = file_size;
5682 SYMS_QueuePush(file_list.first, file_list.last, node);
5683 file_list.node_count += 1;
5684 }
5685
5686 //- rjf: build dir table
5687 {
5688 header_out->dir_table.count = dir_list.node_count;
5689 header_out->dir_table.strings = syms_push_array(arena, SYMS_String8, header_out->dir_table.count);
5690 SYMS_String8Node *n = dir_list.first;
5691 for(SYMS_U64 idx = 0; n != 0 && idx < header_out->dir_table.count; idx += 1, n = n->next)
5692 {
5693 SYMS_String8 string = syms_push_string_copy(arena, n->string);
5694 header_out->dir_table.strings[idx] = string;
5695 }
5696 }
5697
5698 //- rjf: build file table
5699 {
5700 header_out->file_table.count = file_list.node_count;
5701 header_out->file_table.v = syms_push_array(arena, SYMS_DwLineFile, header_out->file_table.count);
5702 SYMS_U64 file_idx = 0;
5704 for(; file_node != 0; file_idx += 1, file_node = file_node->next)
5705 {
5706 SYMS_String8 file_name = syms_push_string_copy(arena, file_node->file.file_name);
5707 header_out->file_table.v[file_idx].file_name = file_name;
5708 header_out->file_table.v[file_idx].dir_idx = file_node->file.dir_idx;
5709 header_out->file_table.v[file_idx].modify_time = file_node->file.modify_time;
5710 header_out->file_table.v[file_idx].file_size = file_node->file.file_size;
5711 }
5712 }
5713 }
5715
5716 SYMS_U64 result = line_off - line_off_start;
5717 return result;
5718}
5719
5720//- rjf: name maps
5721
5724{
5727 {
5728 result = syms_push_array(arena, SYMS_DwMapAccel, 1);
5729 syms_memzero_struct(result);
5730 result->format = SYMS_FileFormat_DWARF;
5732 }
5733 return result;
5734}
5735
5749
5755
5756#endif // SYMS_DWARF_PARSER_C
OODEFFUNC typedef const char * file
Definition oodle2.h:678
OODEFFUNC typedef const char int line
Definition oodle2.h:678
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
bool left(const int *a, const int *b, const int *c)
Definition RecastMesh.cpp:182
int next(int i, int n)
Definition RecastMesh.cpp:164
char * dst
Definition lz4.h:735
float v
Definition radaudio_mdct.cpp:62
Definition syms_base.h:402
Definition syms_debug_info.h:300
SYMS_U64 val
Definition syms_debug_info.h:303
SYMS_TypeKind kind
Definition syms_debug_info.h:302
Definition syms_dwarf_parser.h:63
SYMS_U64 id
Definition syms_dwarf_parser.h:64
SYMS_U64 off
Definition syms_dwarf_parser.h:65
Definition syms_dwarf_parser.h:70
SYMS_U64 count
Definition syms_dwarf_parser.h:71
SYMS_DwAbbrevTableEntry * entries
Definition syms_dwarf_parser.h:72
Definition syms_dwarf_parser.h:164
SYMS_U64Range abbrev_range
Definition syms_dwarf_parser.h:166
SYMS_U64 id
Definition syms_dwarf_parser.h:168
Definition syms_dwarf_parser.h:231
SYMS_U64 max_abbrev_off
Definition syms_dwarf_parser.h:234
SYMS_DwAttribList attribs
Definition syms_dwarf_parser.h:232
SYMS_U64 max_info_off
Definition syms_dwarf_parser.h:233
Definition syms_dwarf_parser.h:223
SYMS_DwAttribNode * last
Definition syms_dwarf_parser.h:225
SYMS_DwAttribNode * first
Definition syms_dwarf_parser.h:224
SYMS_U64 count
Definition syms_dwarf_parser.h:226
Definition syms_dwarf_parser.h:216
SYMS_DwAttrib attrib
Definition syms_dwarf_parser.h:218
Definition syms_dwarf_parser.h:178
SYMS_U64 debug_str_offs_base
Definition syms_dwarf_parser.h:185
SYMS_U64 debug_rnglists_base
Definition syms_dwarf_parser.h:184
SYMS_U64 containing_unit_info_off
Definition syms_dwarf_parser.h:182
SYMS_U64 debug_addrs_base
Definition syms_dwarf_parser.h:183
SYMS_U64 debug_loclists_base
Definition syms_dwarf_parser.h:186
SYMS_DwLanguage language
Definition syms_dwarf_parser.h:180
SYMS_U64 addr_size
Definition syms_dwarf_parser.h:181
SYMS_DwVersion version
Definition syms_dwarf_parser.h:179
Definition syms_dwarf_parser.h:191
SYMS_U64 v[2]
Definition syms_dwarf_parser.h:193
SYMS_DwSectionKind section
Definition syms_dwarf_parser.h:192
Definition syms_dwarf_parser.h:198
SYMS_DwAttribClass value_class
Definition syms_dwarf_parser.h:203
SYMS_DwAttribValue form_value
Definition syms_dwarf_parser.h:204
SYMS_U64 abbrev_id
Definition syms_dwarf_parser.h:200
SYMS_U64 info_off
Definition syms_dwarf_parser.h:199
SYMS_DwAttribKind attrib_kind
Definition syms_dwarf_parser.h:201
SYMS_DwFormKind form_kind
Definition syms_dwarf_parser.h:202
Definition syms_dwarf_parser.h:242
SYMS_U64 addrs_base
Definition syms_dwarf_parser.h:257
SYMS_DwLineVMFileArray file_table
Definition syms_dwarf_parser.h:277
SYMS_U64Range tags_info_range
Definition syms_dwarf_parser.h:251
SYMS_DwAbbrevTable abbrev_table
Definition syms_dwarf_parser.h:252
SYMS_B32 use_utf8
Definition syms_dwarf_parser.h:268
SYMS_U64 dwo_id
Definition syms_dwarf_parser.h:265
SYMS_U64 loclist_base
Definition syms_dwarf_parser.h:256
SYMS_DwAttribValue ranges_attrib_value
Definition syms_dwarf_parser.h:272
SYMS_U64 abbrev_off
Definition syms_dwarf_parser.h:248
SYMS_U64 low_pc
Definition syms_dwarf_parser.h:270
SYMS_U64 high_pc
Definition syms_dwarf_parser.h:271
SYMS_U64 rnglist_base
Definition syms_dwarf_parser.h:255
SYMS_U64 size
Definition syms_dwarf_parser.h:244
SYMS_U64 address_size
Definition syms_dwarf_parser.h:247
SYMS_U64 info_off
Definition syms_dwarf_parser.h:249
SYMS_String8 external_dwo_name
Definition syms_dwarf_parser.h:264
SYMS_String8Array dir_table
Definition syms_dwarf_parser.h:276
SYMS_U64 name_case
Definition syms_dwarf_parser.h:267
SYMS_U64 index
Definition syms_dwarf_parser.h:250
SYMS_String8 name
Definition syms_dwarf_parser.h:261
SYMS_String8 compile_dir
Definition syms_dwarf_parser.h:263
SYMS_String8 producer
Definition syms_dwarf_parser.h:262
SYMS_U64 line_off
Definition syms_dwarf_parser.h:269
SYMS_U64 stroffs_base
Definition syms_dwarf_parser.h:258
SYMS_DwCompUnitKind kind
Definition syms_dwarf_parser.h:245
SYMS_DwVersion version
Definition syms_dwarf_parser.h:246
SYMS_DwLanguage language
Definition syms_dwarf_parser.h:266
SYMS_U64 base_addr
Definition syms_dwarf_parser.h:273
Definition syms_dwarf_parser.h:94
SYMS_U64 text_section_idx
Definition syms_dwarf_parser.h:99
SYMS_DwUnitRangeInfo * unit_range_info
Definition syms_dwarf_parser.h:103
SYMS_U64Range acceptable_vrange
Definition syms_dwarf_parser.h:100
SYMS_DwSection * section_map
Definition syms_dwarf_parser.h:101
SYMS_Arch arch
Definition syms_dwarf_parser.h:96
SYMS_FileFormat format
Definition syms_dwarf_parser.h:95
SYMS_U64 vbase
Definition syms_dwarf_parser.h:97
SYMS_SecInfoArray sections
Definition syms_dwarf_parser.h:98
SYMS_U64 unit_count
Definition syms_dwarf_parser.h:102
SYMS_B32 is_dwo
Definition syms_dwarf_parser.h:104
Definition syms_dwarf_parser.h:52
SYMS_String8 dwo_path
Definition syms_dwarf_parser.h:54
SYMS_U64 dwo_id
Definition syms_dwarf_parser.h:55
Definition syms_dwarf_parser.h:112
SYMS_String8 file_name
Definition syms_dwarf_parser.h:113
SYMS_U64 dir_idx
Definition syms_dwarf_parser.h:114
SYMS_U64 modify_time
Definition syms_dwarf_parser.h:115
SYMS_U64 file_size
Definition syms_dwarf_parser.h:117
Definition syms_dwarf_parser.h:430
SYMS_Line line
Definition syms_dwarf_parser.h:432
Definition syms_dwarf_parser.h:437
Definition syms_dwarf_parser.h:446
SYMS_DwLineSeqNode * last_seq
Definition syms_dwarf_parser.h:449
SYMS_U64 count
Definition syms_dwarf_parser.h:138
SYMS_DwLineFile * v
Definition syms_dwarf_parser.h:139
Definition syms_dwarf_parser.h:129
Definition syms_dwarf_parser.h:122
SYMS_DwLineFile file
Definition syms_dwarf_parser.h:124
Definition syms_dwarf_parser.h:375
Definition syms_dwarf_parser.h:397
SYMS_U64 discriminator
Definition syms_dwarf_parser.h:419
SYMS_U32 op_index
Definition syms_dwarf_parser.h:399
SYMS_U32 line
Definition syms_dwarf_parser.h:406
SYMS_U64 isa
Definition syms_dwarf_parser.h:418
SYMS_B32 epilogue_begin
Definition syms_dwarf_parser.h:417
SYMS_B32 prologue_end
Definition syms_dwarf_parser.h:415
SYMS_U32 column
Definition syms_dwarf_parser.h:407
SYMS_B32 is_stmt
Definition syms_dwarf_parser.h:409
SYMS_U64 address
Definition syms_dwarf_parser.h:398
SYMS_U32 file_index
Definition syms_dwarf_parser.h:404
SYMS_B32 basic_block
Definition syms_dwarf_parser.h:410
Definition syms_dwarf_parser.h:557
SYMS_FileFormat format
Definition syms_dwarf_parser.h:558
SYMS_DwPubStringsTable tbl
Definition syms_dwarf_parser.h:559
Definition syms_dwarf_parser.h:543
SYMS_MemInfo * mem_infos
Definition syms_dwarf_parser.h:546
SYMS_USID * full_symbols
Definition syms_dwarf_parser.h:548
SYMS_SymbolID * sig_symbols
Definition syms_dwarf_parser.h:549
SYMS_U64 count
Definition syms_dwarf_parser.h:545
SYMS_USID * type_symbols
Definition syms_dwarf_parser.h:547
Definition syms_dwarf_parser.h:457
Definition syms_dwarf_parser.h:466
SYMS_DwPubStringsBucket ** buckets
Definition syms_dwarf_parser.h:468
SYMS_U64 size
Definition syms_dwarf_parser.h:467
Definition syms_dwarf_parser.h:80
SYMS_U64Range range
Definition syms_dwarf_parser.h:81
Definition syms_dwarf_expr.h:159
SYMS_DwSimpleLocKind kind
Definition syms_dwarf_expr.h:160
SYMS_U64 addr
Definition syms_dwarf_expr.h:162
Definition syms_dwarf_parser.h:40
Definition syms_dwarf_parser.h:32
Definition syms_dwarf_parser.h:476
SYMS_SymbolID dst
Definition syms_dwarf_parser.h:478
SYMS_SymbolID src
Definition syms_dwarf_parser.h:479
Definition syms_dwarf_parser.h:484
SYMS_DwTagRefNode ** v
Definition syms_dwarf_parser.h:486
SYMS_U64 size
Definition syms_dwarf_parser.h:485
Definition syms_dwarf_parser.h:494
SYMS_DwTagStubCacheNode * first
Definition syms_dwarf_parser.h:497
SYMS_DwTagStubCacheNode * last
Definition syms_dwarf_parser.h:498
SYMS_DwTagStub stub
Definition syms_dwarf_parser.h:500
SYMS_U64 children_count
Definition syms_dwarf_parser.h:499
Definition syms_dwarf_parser.h:364
SYMS_U64 count
Definition syms_dwarf_parser.h:367
SYMS_DwTagStubNode * first
Definition syms_dwarf_parser.h:365
Definition syms_dwarf_parser.h:357
SYMS_DwTagStub stub
Definition syms_dwarf_parser.h:359
Definition syms_dwarf_parser.h:327
SYMS_SymbolID sid
Definition syms_dwarf_parser.h:328
SYMS_SymbolID abstract_origin
Definition syms_dwarf_parser.h:350
SYMS_U64 children_info_off
Definition syms_dwarf_parser.h:331
SYMS_SymbolID ref
Definition syms_dwarf_parser.h:342
SYMS_U64 attribs_abbrev_off
Definition syms_dwarf_parser.h:333
SYMS_DwTagKind kind
Definition syms_dwarf_parser.h:329
SYMS_U64 attribs_info_off
Definition syms_dwarf_parser.h:332
SYMS_DwTagStubFlags flags
Definition syms_dwarf_parser.h:330
Definition syms_dwarf_parser.h:301
SYMS_U64Range abbrev_range
Definition syms_dwarf_parser.h:307
SYMS_DwTagKind kind
Definition syms_dwarf_parser.h:310
SYMS_U64 abbrev_id
Definition syms_dwarf_parser.h:309
SYMS_U64 attribs_info_off
Definition syms_dwarf_parser.h:311
SYMS_U64Range info_range
Definition syms_dwarf_parser.h:306
SYMS_B32 has_children
Definition syms_dwarf_parser.h:308
SYMS_U64 attribs_abbrev_off
Definition syms_dwarf_parser.h:312
SYMS_DwAttribList attribs
Definition syms_dwarf_parser.h:313
Definition syms_dwarf_parser.h:505
SYMS_DwAttribValueResolveParams resolve_params
Definition syms_dwarf_parser.h:535
SYMS_U64 stub_table_size
Definition syms_dwarf_parser.h:518
SYMS_DwAbbrevTable abbrev_table
Definition syms_dwarf_parser.h:515
SYMS_DwTagRefTable parent_table
Definition syms_dwarf_parser.h:523
SYMS_SymbolIDArray all_top_ids
Definition syms_dwarf_parser.h:529
SYMS_SymbolIDArray var_ids
Definition syms_dwarf_parser.h:531
SYMS_DwTagRefTable ref_table
Definition syms_dwarf_parser.h:522
SYMS_DwTagStubCacheNode ** stub_table
Definition syms_dwarf_parser.h:519
SYMS_DwVersion version
Definition syms_dwarf_parser.h:510
SYMS_DwLanguage language
Definition syms_dwarf_parser.h:514
SYMS_U64 addrs_base
Definition syms_dwarf_parser.h:513
SYMS_FileFormat format
Definition syms_dwarf_parser.h:506
SYMS_U64 base_addr
Definition syms_dwarf_parser.h:512
SYMS_SymbolIDArray type_ids
Definition syms_dwarf_parser.h:532
SYMS_U64 address_size
Definition syms_dwarf_parser.h:511
SYMS_SymbolIDArray proc_ids
Definition syms_dwarf_parser.h:530
SYMS_DwTagStubCacheNode * stub_root
Definition syms_dwarf_parser.h:526
SYMS_UnitID uid
Definition syms_dwarf_parser.h:509
Definition syms_dwarf_parser.h:86
SYMS_U64RangeArray addr_ranges
Definition syms_dwarf_parser.h:89
SYMS_UnitID uid
Definition syms_dwarf_parser.h:87
SYMS_U64Range frange
Definition syms_dwarf_parser.h:88
Definition syms_dwarf_parser.h:24
Definition syms_dwarf_parser.h:290
Definition syms_elf_parser.h:68
SYMS_ElfImgHeader header
Definition syms_elf_parser.h:70
SYMS_Arch arch
Definition syms_elf_parser.h:16
Definition syms_debug_info.h:346
Definition syms_debug_info.h:341
SYMS_String8 name
Definition syms_debug_info.h:342
SYMS_U64 val
Definition syms_debug_info.h:343
Definition syms_debug_info.h:119
Definition syms_debug_info.h:114
SYMS_ExtFile ext_file
Definition syms_debug_info.h:116
SYMS_String8 file_name
Definition syms_debug_info.h:110
SYMS_ExtMatchKey match_key
Definition syms_debug_info.h:111
Definition syms_debug_info.h:105
SYMS_U8 v[16]
Definition syms_debug_info.h:106
Definition syms_debug_info.h:164
SYMS_LineTable line_table
Definition syms_debug_info.h:165
SYMS_U64 line_count
Definition syms_debug_info.h:161
SYMS_Line * line_array
Definition syms_debug_info.h:160
SYMS_U64 * sequence_index_array
Definition syms_debug_info.h:157
SYMS_U64 sequence_count
Definition syms_debug_info.h:158
Definition syms_debug_info.h:136
SYMS_U64 voff
Definition syms_debug_info.h:138
SYMS_SrcCoord src_coord
Definition syms_debug_info.h:137
Definition syms_debug_info.h:361
SYMS_LocRange * loc_ranges
Definition syms_debug_info.h:362
SYMS_U64 count
Definition syms_debug_info.h:363
Definition syms_debug_info.h:371
Definition syms_debug_info.h:366
SYMS_LocRange loc_range
Definition syms_debug_info.h:368
Definition syms_debug_info.h:356
SYMS_LocID loc_id
Definition syms_debug_info.h:358
SYMS_U64Range vrange
Definition syms_debug_info.h:357
Definition syms_eval.h:62
Definition syms_mach_parser.h:40
SYMS_Arch arch
Definition syms_mach_parser.h:43
Definition syms_debug_info.h:325
Definition syms_debug_info.h:21
SYMS_U64 count
Definition syms_debug_info.h:23
SYMS_SecInfo * sec_info
Definition syms_debug_info.h:22
Definition syms_debug_info.h:15
SYMS_U64Range vrange
Definition syms_debug_info.h:17
SYMS_String8 name
Definition syms_debug_info.h:16
SYMS_U64Range frange
Definition syms_debug_info.h:18
Definition syms_debug_info.h:255
Definition syms_debug_info.h:334
SYMS_SymbolIDArray param_type_ids
Definition syms_debug_info.h:336
SYMS_SymbolID this_type_id
Definition syms_debug_info.h:338
SYMS_SymbolID return_type_id
Definition syms_debug_info.h:337
SYMS_UnitID uid
Definition syms_debug_info.h:335
SYMS_FileID file_id
Definition syms_debug_info.h:131
SYMS_U32 line
Definition syms_debug_info.h:132
SYMS_U32 col
Definition syms_debug_info.h:133
Definition syms_base.h:313
SYMS_String8 * strings
Definition syms_base.h:314
SYMS_U64 count
Definition syms_base.h:315
Definition syms_base.h:306
Definition syms_base.h:301
SYMS_String8 string
Definition syms_base.h:303
struct SYMS_String8Node * next
Definition syms_base.h:302
Definition syms_base.h:296
SYMS_U8 * str
Definition syms_base.h:297
SYMS_U64 size
Definition syms_base.h:298
Definition syms_base.h:325
SYMS_String8 pre
Definition syms_base.h:326
Definition syms_debug_info.h:228
SYMS_SymbolID * ids
Definition syms_debug_info.h:229
SYMS_U64 count
Definition syms_debug_info.h:230
Definition syms_debug_info.h:222
Definition syms_debug_info.h:217
SYMS_SymbolID id
Definition syms_debug_info.h:219
Definition syms_debug_info.h:264
SYMS_U64 reported_size
Definition syms_debug_info.h:275
SYMS_USID direct_type
Definition syms_debug_info.h:290
SYMS_SizeInterpretation reported_size_interp
Definition syms_debug_info.h:274
SYMS_TypeKind kind
Definition syms_debug_info.h:265
SYMS_USID containing_type
Definition syms_debug_info.h:296
SYMS_TypeModifiers mods
Definition syms_debug_info.h:271
SYMS_CallConvention call_convention
Definition syms_debug_info.h:294
SYMS_SrcCoord src_coord
Definition syms_debug_info.h:278
Definition syms_base.h:280
SYMS_U64Range * ranges
Definition syms_base.h:281
SYMS_U64 count
Definition syms_base.h:282
Definition syms_base.h:274
SYMS_U64 node_count
Definition syms_base.h:277
Definition syms_base.h:269
Definition syms_base.h:264
SYMS_U64 max
Definition syms_base.h:266
SYMS_U64 min
Definition syms_base.h:265
Definition syms_debug_info.h:244
Definition syms_debug_info.h:239
SYMS_USID usid
Definition syms_debug_info.h:241
Definition syms_debug_info.h:234
SYMS_UnitID uid
Definition syms_debug_info.h:235
SYMS_SymbolID sid
Definition syms_debug_info.h:236
Definition syms_debug_info.h:259
Definition syms_debug_info.h:79
SYMS_Language language
Definition syms_debug_info.h:81
SYMS_UnitFeatures features
Definition syms_debug_info.h:80
Definition syms_debug_info.h:84
SYMS_String8 source_file
Definition syms_debug_info.h:85
SYMS_String8 compile_dir
Definition syms_debug_info.h:89
SYMS_String8 compiler
Definition syms_debug_info.h:88
Definition syms_debug_info.h:97
SYMS_U64 count
Definition syms_debug_info.h:99
SYMS_UnitRange * ranges
Definition syms_debug_info.h:98
Definition syms_debug_info.h:92
SYMS_U64Range vrange
Definition syms_debug_info.h:93
SYMS_UnitID uid
Definition syms_debug_info.h:94
SYMS_API SYMS_U64 syms_u64_range_size(SYMS_U64Range range)
Definition syms_base.c:31
SYMS_API SYMS_U64 syms_based_range_read(void *base, SYMS_U64Range range, SYMS_U64 offset, SYMS_U64 out_size, void *out)
Definition syms_base.c:753
SYMS_API SYMS_String8 syms_string_list_join(SYMS_Arena *arena, SYMS_String8List *list, SYMS_StringJoin *join_ptr)
Definition syms_base.c:315
SYMS_API void syms_u64_range_list_concat(SYMS_U64RangeList *list, SYMS_U64RangeList *to_push)
Definition syms_base.c:570
SYMS_API SYMS_ArenaTemp syms_get_scratch(SYMS_Arena **conflicts, SYMS_U64 conflict_count)
Definition syms_base.c:694
SYMS_API SYMS_B32 syms_string_match(SYMS_String8 a, SYMS_String8 b, SYMS_StringMatchFlags flags)
Definition syms_base.c:210
SYMS_API void * syms_based_range_ptr(void *base, SYMS_U64Range range, SYMS_U64 offset)
Definition syms_base.c:744
SYMS_API SYMS_String8 syms_string_trunc_symbol_heuristic(SYMS_String8 string)
Definition syms_base.c:361
SYMS_API void syms_u64_range_list_push(SYMS_Arena *arena, SYMS_U64RangeList *list, SYMS_U64Range range)
Definition syms_base.c:564
SYMS_API SYMS_U64Range syms_make_u64_range(SYMS_U64 min, SYMS_U64 max)
Definition syms_base.c:18
SYMS_API SYMS_U64RangeArray syms_u64_range_array_from_list(SYMS_Arena *arena, SYMS_U64RangeList *list)
Definition syms_base.c:585
SYMS_API SYMS_U64 syms_based_range_read_sleb128(void *base, SYMS_U64Range range, SYMS_U64 offset, SYMS_S64 *out_value)
Definition syms_base.c:792
SYMS_API SYMS_String8 syms_based_range_read_string(void *base, SYMS_U64Range range, SYMS_U64 offset)
Definition syms_base.c:823
SYMS_API void syms_arena_temp_end(SYMS_ArenaTemp temp)
Definition syms_base.c:689
SYMS_API SYMS_String8 syms_str8(SYMS_U8 *str, SYMS_U64 size)
Definition syms_base.c:169
SYMS_API SYMS_U64 syms_based_range_read_uleb128(void *base, SYMS_U64Range range, SYMS_U64 offset, SYMS_U64 *out_value)
Definition syms_base.c:765
SYMS_API SYMS_String8 syms_push_string_copy(SYMS_Arena *arena, SYMS_String8 string)
Definition syms_base.c:353
SYMS_API void syms_string_list_push(SYMS_Arena *arena, SYMS_String8List *list, SYMS_String8 string)
Definition syms_base.c:282
SYMS_API SYMS_ArenaTemp syms_arena_temp_begin(SYMS_Arena *arena)
Definition syms_base.c:682
float SYMS_F32
Definition syms_base.h:101
#define syms_true
Definition syms_base.h:105
#define syms_str8_comp(s)
Definition syms_base.h:482
#define SYMS_MIN(a, b)
Definition syms_base.h:179
#define SYMS_Swap(T, a, b)
Definition syms_base.h:190
double SYMS_F64
Definition syms_base.h:102
#define SYMS_StackPush(f, n)
Definition syms_base.h:227
#define syms_based_range_read_struct(b, r, o, p)
Definition syms_base.h:593
#define syms_push_array(a, T, c)
Definition syms_base.h:561
#define syms_memzero_struct(s)
Definition syms_base.h:161
#define SYMS_AlignPow2(a, b)
Definition syms_base.h:187
#define SYMS_LOCAL
Definition syms_base.h:43
#define SYMS_StackPush_N(f, n, next)
Definition syms_base.h:224
@ SYMS_StringMatchFlag_RightSideSloppy
Definition syms_base.h:321
#define SYMS_READ_ONLY
Definition syms_base.h:57
#define SYMS_INVALID_CODE_PATH
Definition syms_base.h:142
#define syms_expand_string(s)
Definition syms_base.h:484
#define syms_false
Definition syms_base.h:104
#define SYMS_API
Definition syms_base.h:29
#define SYMS_ARRAY_SIZE(x)
Definition syms_base.h:144
SYMS_S32 SYMS_B32
Definition syms_base.h:99
#define syms_push_array_zero(a, T, c)
Definition syms_base.h:564
#define SYMS_MAX(a, b)
Definition syms_base.h:180
#define syms_string_from_enum_value(enum_type, value)
Definition syms_base.h:461
#define SYMS_ASSERT_PARANOID(x)
Definition syms_base.h:132
#define SYMS_U64_MAX
Definition syms_base.h:176
#define syms_str8_lit(s)
Definition syms_base.h:483
#define SYMS_QueuePush(f, l, n)
Definition syms_base.h:220
#define syms_release_scratch
Definition syms_base.h:567
#define SYMS_GLOBAL
Definition syms_base.h:42
int32_t SYMS_S32
Definition syms_crt_overrides.h:34
uint32_t SYMS_U32
Definition syms_crt_overrides.h:38
#define SYMS_U8
Definition syms_crt_overrides.h:51
#define SYMS_PRIu64
Definition syms_crt_overrides.h:41
#define SYMS_U16
Definition syms_crt_overrides.h:52
uint64_t SYMS_U64
Definition syms_crt_overrides.h:39
#define syms_memmove
Definition syms_crt_overrides.h:65
#define SYMS_U64
Definition syms_crt_overrides.h:54
#define SYMS_U32
Definition syms_crt_overrides.h:53
uint16_t SYMS_U16
Definition syms_crt_overrides.h:37
int64_t SYMS_S64
Definition syms_crt_overrides.h:35
#define SYMS_S32
Definition syms_crt_overrides.h:49
#define SYMS_S64
Definition syms_crt_overrides.h:50
#define SYMS_PRIx64
Definition syms_crt_overrides.h:43
#define syms_memset
Definition syms_crt_overrides.h:66
uint8_t SYMS_U8
Definition syms_crt_overrides.h:36
SYMS_API void syms_push_sid_to_list(SYMS_Arena *arena, SYMS_SymbolIDList *list, SYMS_SymbolID id)
Definition syms_debug_info.c:28
SYMS_API SYMS_SymbolIDArray syms_sid_array_from_list(SYMS_Arena *arena, SYMS_SymbolIDList *list)
Definition syms_debug_info.c:115
SYMS_U32 SYMS_MemFlags
Definition syms_debug_info.h:318
SYMS_ProcLoc
Definition syms_debug_info.h:377
@ SYMS_ProcLoc_FrameBase
Definition syms_debug_info.h:378
@ SYMS_ProcLoc_ReturnAddress
Definition syms_debug_info.h:379
SYMS_U64 SYMS_UnitID
Definition syms_debug_info.h:77
SYMS_U64 SYMS_FileID
Definition syms_debug_info.h:128
SYMS_SizeInterpretation
Definition syms_debug_info.h:205
@ SYMS_SizeInterpretation_ByteCount
Definition syms_debug_info.h:207
@ SYMS_SizeInterpretation_Multiplier
Definition syms_debug_info.h:208
SYMS_U64 SYMS_SymbolID
Definition syms_debug_info.h:215
SYMS_U64 SYMS_LocID
Definition syms_debug_info.h:354
@ SYMS_MemFlag_Destructor
Definition syms_debug_info.h:322
@ SYMS_MemFlag_Constructor
Definition syms_debug_info.h:321
@ SYMS_MemFlag_Virtual
Definition syms_debug_info.h:320
SYMS_MemKind
Definition syms_debug_info.h:306
@ SYMS_MemKind_StaticMethod
Definition syms_debug_info.h:311
@ SYMS_MemKind_Null
Definition syms_debug_info.h:307
@ SYMS_MemKind_VBaseClassPtr
Definition syms_debug_info.h:314
@ SYMS_MemKind_StaticData
Definition syms_debug_info.h:309
@ SYMS_MemKind_NestedType
Definition syms_debug_info.h:315
@ SYMS_MemKind_Method
Definition syms_debug_info.h:310
@ SYMS_MemKind_DataField
Definition syms_debug_info.h:308
@ SYMS_MemKind_BaseClass
Definition syms_debug_info.h:313
SYMS_READ_ONLY SYMS_GLOBAL SYMS_FileFormat syms_format_nil
Definition syms_debug_info.h:398
#define SYMS_Arena
Definition syms_default_arena.h:61
#define SYMS_LogClose(block)
Definition syms_dev.h:142
#define SYMS_LogOpen(ftr, uid, block)
Definition syms_dev.h:141
#define SYMS_ProfEnd()
Definition syms_dev.h:212
#define SYMS_ProfBegin(str)
Definition syms_dev.h:209
@ SYMS_LogFeature_DwarfTags
Definition syms_dev.h:22
@ SYMS_LogFeature_LineTable
Definition syms_dev.h:20
@ SYMS_LogFeature_DwarfUnitRanges
Definition syms_dev.h:21
#define SYMS_Log(fmt,...)
Definition syms_dev.h:143
SYMS_API SYMS_B32 syms_dw_are_attrib_class_and_form_kind_compatible(SYMS_DwAttribClass attrib_class, SYMS_DwFormKind form_kind)
Definition syms_dwarf.c:126
SYMS_API SYMS_String8 syms_dw_name_string_from_section_kind(SYMS_DwSectionKind kind)
Definition syms_dwarf.c:17
SYMS_API SYMS_DwAttribClass syms_dw_attrib_class_from_form_kind_v2(SYMS_DwFormKind form)
Definition syms_dwarf.c:473
SYMS_API SYMS_TypeKind syms_dw_type_kind_from_tag_encoding_size(SYMS_DwTagKind tag_kind, SYMS_DwAttribTypeEncoding encoding, SYMS_U64 size)
Definition syms_dwarf.c:229
SYMS_API SYMS_DwAttribClass syms_dw_attrib_class_from_attrib_kind_v2(SYMS_DwAttribKind attrib)
Definition syms_dwarf.c:404
SYMS_API SYMS_U64 syms_dw_offset_size_from_mode(SYMS_DwMode mode)
Definition syms_dwarf.c:113
SYMS_API SYMS_TypeModifiers syms_dw_type_modifiers_from_tag_kind(SYMS_DwTagKind tag_kind)
Definition syms_dwarf.c:319
SYMS_API SYMS_String8 syms_dw_mach_name_string_from_section_kind(SYMS_DwSectionKind kind)
Definition syms_dwarf.c:49
SYMS_API SYMS_String8 syms_dw_dwo_name_string_from_section_kind(SYMS_DwSectionKind kind)
Definition syms_dwarf.c:81
SYMS_DwLNCT
Definition syms_dwarf.h:30
@ SYMS_DwLNCT_USER_LO
Definition syms_dwarf.h:36
@ SYMS_DwLNCT_MD5
Definition syms_dwarf.h:35
@ SYMS_DwLNCT_PATH
Definition syms_dwarf.h:31
@ SYMS_DwLNCT_DIRECTORY_INDEX
Definition syms_dwarf.h:32
@ SYMS_DwLNCT_USER_HI
Definition syms_dwarf.h:37
@ SYMS_DwLNCT_SIZE
Definition syms_dwarf.h:34
@ SYMS_DwLNCT_TIMESTAMP
Definition syms_dwarf.h:33
SYMS_DwCompUnitKind
Definition syms_dwarf.h:16
@ SYMS_DwCompUnitKind_RESERVED
Definition syms_dwarf.h:17
@ SYMS_DwCompUnitKind_SKELETON
Definition syms_dwarf.h:21
SYMS_API SYMS_DwSimpleLoc syms_dw_expr__analyze_fast(void *base, SYMS_U64Range range, SYMS_U64 text_section_base)
Definition syms_dwarf_expr.c:17
@ SYMS_DwSimpleLocKind_Address
Definition syms_dwarf_expr.h:128
SYMS_API SYMS_String8Array syms_dw_file_table_from_uid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitSetAccel *unit_set, SYMS_UnitID uid)
Definition syms_dwarf_parser.c:2993
SYMS_API SYMS_U64 syms_dw_unit_number_from_uid(SYMS_DwUnitSetAccel *accel, SYMS_UnitID uid)
Definition syms_dwarf_parser.c:2710
SYMS_API SYMS_ExtFileList syms_dw_ext_file_list_from_dbg(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg)
Definition syms_dwarf_parser.c:1038
SYMS_API SYMS_U64 syms_dw_abbrev_offset_from_abbrev_id(SYMS_DwAbbrevTable table, SYMS_U64 abbrev_id)
Definition syms_dwarf_parser.c:1236
SYMS_API SYMS_LocRangeArray syms_dw_location_ranges_from_proc_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid, SYMS_ProcLoc proc_loc)
Definition syms_dwarf_parser.c:4826
SYMS_API SYMS_DwUnitAccel * syms_dw_unit_accel_from_uid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitSetAccel *unit_set, SYMS_UnitID uid)
Definition syms_dwarf_parser.c:3642
SYMS_API SYMS_ExtMatchKey syms_dw_ext_match_key_from_dbg(SYMS_String8 data, SYMS_DwDbgAccel *dbg)
Definition syms_dwarf_parser.c:1072
SYMS_API SYMS_SecInfoArray syms_dw_copy_sec_info_array(SYMS_Arena *arena, SYMS_SecInfoArray array)
Definition syms_dwarf_parser.c:310
SYMS_API SYMS_MemInfo syms_dw_mem_info_from_number(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_DwMemsAccel *mems, SYMS_U64 n)
Definition syms_dwarf_parser.c:4079
SYMS_API SYMS_DwAttribListParseResult syms_dw_parse_attrib_list_from_info_abbrev_offsets(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwLanguage lang, SYMS_DwVersion ver, SYMS_U64 address_size, SYMS_U64 info_off, SYMS_U64 abbrev_off)
Definition syms_dwarf_parser.c:2129
SYMS_API SYMS_FileID syms_dw_file_id_from_index(SYMS_U64 idx)
Definition syms_dwarf_parser.c:4843
SYMS_API SYMS_DwAbbrevTable syms_dw_make_abbrev_table(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_U64 abbrev_offset)
Definition syms_dwarf_parser.c:1159
SYMS_API SYMS_DwLineTableParseResult syms_dw_parsed_line_table_from_comp_root(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwCompRoot *root)
Definition syms_dwarf_parser.c:5130
SYMS_API SYMS_U64 syms_dw_voff_from_var_sid(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4591
SYMS_API SYMS_String8 syms_dw_attrib_string_from_sid__unstable_chain(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_DwAttribKind kind, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4266
SYMS_API SYMS_DwMemsAccel * syms_dw_mems_accel_from_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:3800
SYMS_API SYMS_U64RangeList syms_dw_v4_range_list_from_range_offset(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_U64 addr_size, SYMS_U64 comp_unit_base_addr, SYMS_U64 range_off)
Definition syms_dwarf_parser.c:1270
SYMS_API SYMS_U64 syms_dw_unit_count_from_set(SYMS_DwUnitSetAccel *accel)
Definition syms_dwarf_parser.c:2687
SYMS_API SYMS_String8 syms_dw_path_from_dir_and_filename(SYMS_Arena *arena, SYMS_String8 dir, SYMS_String8 filename)
Definition syms_dwarf_parser.c:325
SYMS_API void syms_dw_tag_ref_table_insert(SYMS_Arena *arena, SYMS_DwTagRefTable *table, SYMS_SymbolID src, SYMS_SymbolID dst)
Definition syms_dwarf_parser.c:3031
SYMS_API SYMS_USIDList syms_dw_v4_usid_list_from_pub_table_string(SYMS_Arena *arena, SYMS_DwPubStringsTable tbl, SYMS_String8 string)
Definition syms_dwarf_parser.c:1470
SYMS_API SYMS_LocRangeList syms_dw_v5_location_ranges_from_loclist_offset(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind section, SYMS_U64 addr_size, SYMS_U64 addr_section_base, SYMS_U64 offset)
Definition syms_dwarf_parser.c:1743
SYMS_API SYMS_Location syms_dw_v4_location_from_loc_id(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_LocID id)
Definition syms_dwarf_parser.c:1366
SYMS_API SYMS_String8 syms_dw_attrib_string_from_sid__unstable(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_DwAttribKind kind, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4235
SYMS_API SYMS_LocRangeArray syms_dw_location_ranges_from_var_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4811
SYMS_API SYMS_Location syms_dw_location_from_id(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_LocID loc_id)
Definition syms_dwarf_parser.c:4778
SYMS_API SYMS_DwPubStringsTable syms_dw_v4_pub_strings_table_from_section_kind(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind section_kind)
Definition syms_dwarf_parser.c:1388
SYMS_API SYMS_LineParseOut syms_dw_line_parse_from_uid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitSetAccel *unit_set, SYMS_UnitID uid)
Definition syms_dwarf_parser.c:5380
SYMS_API SYMS_DwDbgAccel * syms_dw_dbg_accel_from_mach_bin(SYMS_Arena *arena, SYMS_String8 data, SYMS_MachBinAccel *bin)
Definition syms_dwarf_parser.c:1028
SYMS_API void syms_dw_line_vm_reset(SYMS_DwLineVMState *state, SYMS_B32 default_is_stmt)
Definition syms_dwarf_parser.c:5068
SYMS_API SYMS_DwExtDebugRef syms_dw_ext_debug_ref_from_comp_root(SYMS_DwCompRoot *root)
Definition syms_dwarf_parser.c:2662
SYMS_API SYMS_U64RangeList syms_dw_v5_range_list_from_rnglist_offset(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind section, SYMS_U64 addr_size, SYMS_U64 addr_section_base, SYMS_U64 offset)
Definition syms_dwarf_parser.c:1645
SYMS_API SYMS_U64RangeList syms_dw_range_list_from_high_low_pc_and_ranges_attrib_value(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_U64 address_size, SYMS_U64 comp_unit_base_addr, SYMS_U64 addr_section_base, SYMS_U64 low_pc, SYMS_U64 high_pc, SYMS_DwAttribValue ranges_value)
Definition syms_dwarf_parser.c:2099
SYMS_API SYMS_DwTagStub syms_dw_stub_from_tag(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwAttribValueResolveParams resolve_params, SYMS_DwTag *tag)
Definition syms_dwarf_parser.c:2276
SYMS_API SYMS_SigInfo syms_dw_sig_info_from_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID id)
Definition syms_dwarf_parser.c:4945
SYMS_API SYMS_DwMode syms_dw_mode_from_sec(SYMS_DwSection *section_map, SYMS_DwSectionKind kind)
Definition syms_dwarf_parser.c:1121
SYMS_READ_ONLY SYMS_GLOBAL SYMS_DwCompRoot syms_dw_nil_comp_root
Definition syms_dwarf_parser.c:66
SYMS_API SYMS_B32 syms_dw_mach_bin_accel_is_dbg(SYMS_MachBinAccel *bin_accel)
Definition syms_dwarf_parser.c:753
SYMS_API SYMS_DwAttribKind syms_dw_attrib_kind_from_proc_loc(SYMS_ProcLoc proc_loc)
Definition syms_dwarf_parser.c:4793
SYMS_API SYMS_SymbolIDArray syms_dw_copy_sid_array_if_needed(SYMS_Arena *arena, SYMS_SymbolIDArray arr)
Definition syms_dwarf_parser.c:3769
SYMS_API SYMS_U64 syms_dw_mem_count_from_mems(SYMS_DwMemsAccel *mems)
Definition syms_dwarf_parser.c:4073
SYMS_API SYMS_UnitID syms_dw_uid_from_accel(SYMS_DwUnitAccel *unit)
Definition syms_dwarf_parser.c:3652
SYMS_API void syms_dw_sort_unit_range_point_array_in_place__merge(SYMS_DwUnitRangePoint *a, SYMS_U64 left, SYMS_U64 right, SYMS_U64 end, SYMS_DwUnitRangePoint *b)
Definition syms_dwarf_parser.c:2740
SYMS_API SYMS_Location syms_dw_location_from_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid, SYMS_DwAttribKind loc_attrib)
Definition syms_dwarf_parser.c:4682
SYMS_API SYMS_U64 syms_dw_hash_from_string(SYMS_String8 string)
Definition syms_dwarf_parser.c:72
SYMS_API SYMS_SymbolKind syms_dw_symbol_kind_from_sid(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4295
SYMS_API SYMS_DwDbgAccel * syms_dw_dbg_accel_from_elf_bin(SYMS_Arena *arena, SYMS_String8 data, SYMS_ElfBinAccel *bin)
Definition syms_dwarf_parser.c:1018
SYMS_API void * syms_dw_sec_base_from_dbg(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind kind)
Definition syms_dwarf_parser.c:1144
SYMS_API SYMS_U64 syms_dw_v5_header_offset_from_table_offset(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind section, SYMS_U64 table_off)
Definition syms_dwarf_parser.c:2314
SYMS_API void syms_dw_symbol_id_chunk_list_push(SYMS_Arena *arena, SYMS_DwSymbolIDChunkList *list, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:394
SYMS_API SYMS_DwLineSeqNode * syms_dw_push_line_seq(SYMS_Arena *arena, SYMS_DwLineTableParseResult *parsed_tbl)
Definition syms_dwarf_parser.c:5091
SYMS_API SYMS_SymbolIDList syms_dw_children_from_sid_with_kinds(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid, SYMS_DwTagKind *kinds, SYMS_U64 count)
Definition syms_dwarf_parser.c:4649
SYMS_API SYMS_UnitID syms_dw_uid_from_foff(SYMS_DwDbgAccel *dbg, SYMS_U64 foff)
Definition syms_dwarf_parser.c:1104
SYMS_API SYMS_U64 syms_dw_based_range_read_length(void *base, SYMS_U64Range range, SYMS_U64 offset, SYMS_U64 *out_value)
Definition syms_dwarf_parser.c:427
SYMS_API SYMS_U64 syms_dw_based_range_read_abbrev_tag(void *base, SYMS_U64Range range, SYMS_U64 offset, SYMS_DwAbbrev *out_abbrev)
Definition syms_dwarf_parser.c:455
SYMS_API SYMS_EnumMemberArray syms_dw_enum_member_array_from_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4134
SYMS_API SYMS_UnitRangeArray syms_dw_unit_ranges_from_set(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitSetAccel *unit_set)
Definition syms_dwarf_parser.c:2782
SYMS_API SYMS_SymbolKind syms_dw_symbol_kind_from_tag_stub(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwAttribValueResolveParams resolve_params, SYMS_DwTagStub *stub)
Definition syms_dwarf_parser.c:198
SYMS_API SYMS_DwUnitAccel * syms_dw_unit_accel_from_comp_root(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwCompRoot *comp_root)
Definition syms_dwarf_parser.c:3120
SYMS_API SYMS_SymbolIDArray syms_dw_var_sid_array_from_unit(SYMS_Arena *arena, SYMS_DwUnitAccel *unit)
Definition syms_dwarf_parser.c:3785
SYMS_API SYMS_U64 syms_dw_v5_sec_offset_from_rnglist_or_loclist_section_base_index(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind section_kind, SYMS_U64 base, SYMS_U64 index)
Definition syms_dwarf_parser.c:1585
SYMS_API SYMS_SecInfoArray syms_dw_sec_info_array_from_dbg(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg)
Definition syms_dwarf_parser.c:1065
SYMS_API SYMS_U64 syms_dw_primify_table_size(SYMS_U64 v)
Definition syms_dwarf_parser.c:3062
SYMS_API SYMS_U64RangeArray syms_dw_scope_vranges_from_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4882
SYMS_API SYMS_DwTag * syms_dw_tag_from_info_offset(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwAbbrevTable abbrev_table, SYMS_DwLanguage lang, SYMS_DwVersion ver, SYMS_U64 address_size, SYMS_U64 info_offset)
Definition syms_dwarf_parser.c:2202
SYMS_API void syms_dw_line_vm_advance(SYMS_DwLineVMState *state, SYMS_U64 advance, SYMS_U64 min_inst_len, SYMS_U64 max_ops_for_inst)
Definition syms_dwarf_parser.c:5083
SYMS_API SYMS_DwMapAccel * syms_dw_type_map_from_dbg(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg)
Definition syms_dwarf_parser.c:5723
SYMS_API SYMS_U64 syms_dw_v5_offset_from_offs_section_base_index(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind section, SYMS_U64 base, SYMS_U64 index)
Definition syms_dwarf_parser.c:1492
SYMS_API SYMS_DwUnitSetAccel * syms_dw_unit_set_accel_from_dbg(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg)
Definition syms_dwarf_parser.c:2672
SYMS_API SYMS_SymbolIDArray syms_dw_scope_children_from_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID id)
Definition syms_dwarf_parser.c:5044
SYMS_API SYMS_Location syms_dw_location_from_proc_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid, SYMS_ProcLoc proc_loc)
Definition syms_dwarf_parser.c:4818
SYMS_API SYMS_USID syms_dw_symbol_from_mem_number(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_DwMemsAccel *mems, SYMS_U64 n)
Definition syms_dwarf_parser.c:4120
SYMS_API SYMS_DwDbgAccel * syms_dw_dbg_accel_from_sec_info_array(SYMS_Arena *arena, SYMS_String8 data, SYMS_U64 vbase, SYMS_Arch arch, SYMS_SecInfoArray sections)
Definition syms_dwarf_parser.c:772
SYMS_API SYMS_U64 syms_dw_read_line_file(void *line_base, SYMS_U64Range line_rng, SYMS_U64 line_off, SYMS_DwMode mode, SYMS_DwDbgAccel *dbg, SYMS_String8 data, SYMS_DwCompRoot *unit, SYMS_U8 address_size, SYMS_U64 format_count, SYMS_U64Range *formats, SYMS_DwLineFile *line_file_out)
Definition syms_dwarf_parser.c:5429
SYMS_API SYMS_SigInfo syms_dw_sig_info_from_mem_number(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_DwMemsAccel *mems, SYMS_U64 n)
Definition syms_dwarf_parser.c:4106
SYMS_API void syms_dw_sort_unit_range_point_array_in_place(SYMS_DwUnitRangePoint *a, SYMS_U64 count)
Definition syms_dwarf_parser.c:2760
SYMS_API SYMS_LocRangeList syms_dw_v4_location_ranges_from_loc_offset(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_U64 addr_size, SYMS_U64 comp_unit_base_addr, SYMS_U64 offset)
Definition syms_dwarf_parser.c:1314
SYMS_API SYMS_DwCompRoot * syms_dw_comp_root_from_uid(SYMS_DwUnitSetAccel *accel, SYMS_UnitID uid)
Definition syms_dwarf_parser.c:2693
SYMS_API SYMS_UnitNames syms_dw_unit_names_from_uid(SYMS_Arena *arena, SYMS_DwUnitSetAccel *unit_set, SYMS_UnitID uid)
Definition syms_dwarf_parser.c:2729
SYMS_API SYMS_LocRangeArray syms_dw_location_ranges_from_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid, SYMS_DwAttribKind loc_attrib)
Definition syms_dwarf_parser.c:4717
SYMS_API SYMS_U64 syms_dw_hash_from_sid(SYMS_SymbolID id)
Definition syms_dwarf_parser.c:84
SYMS_API SYMS_USID syms_dw_type_from_var_sid(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID id)
Definition syms_dwarf_parser.c:4560
SYMS_API SYMS_U64Range syms_dw_sec_range_from_dbg(SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind kind)
Definition syms_dwarf_parser.c:1150
SYMS_API SYMS_U64 syms_dw_predict_good_stub_table_size_from_range_size(SYMS_U64 size)
Definition syms_dwarf_parser.c:3100
SYMS_API SYMS_DwTagStubCacheNode * syms_dw_tag_stub_cache_node_from_sid(SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:3659
SYMS_API SYMS_DwAttribList syms_dw_attrib_list_from_stub(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwLanguage lang, SYMS_DwVersion ver, SYMS_U64 addr_size, SYMS_DwTagStub *stub)
Definition syms_dwarf_parser.c:3762
SYMS_API SYMS_DwTagRefTable syms_dw_tag_ref_table_make(SYMS_Arena *arena, SYMS_U64 size)
Definition syms_dwarf_parser.c:3022
SYMS_API SYMS_Location syms_dw_v5_location_from_loclist_id(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind section, SYMS_LocID id)
Definition syms_dwarf_parser.c:1870
SYMS_API SYMS_String8 syms_dw_symbol_name_from_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4304
SYMS_API SYMS_DwTagStub syms_dw_tag_stub_from_sid(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:3676
SYMS_API SYMS_USID syms_dw_containing_type_from_sid(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4210
SYMS_API SYMS_DwMapAccel * syms_dw_image_symbol_map_from_dbg(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg)
Definition syms_dwarf_parser.c:5737
SYMS_API SYMS_UnitInfo syms_dw_unit_info_from_uid(SYMS_DwUnitSetAccel *unit_set, SYMS_UnitID uid)
Definition syms_dwarf_parser.c:2715
SYMS_API SYMS_Location syms_dw_location_from_var_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4805
SYMS_API SYMS_U64 syms_dw_based_range_read_abbrev_attrib_info(void *base, SYMS_U64Range range, SYMS_U64 offset, SYMS_DwAbbrev *out_abbrev)
Definition syms_dwarf_parser.c:506
SYMS_API SYMS_U64 syms_dw_based_range_read_attrib_form_value(void *base, SYMS_U64Range range, SYMS_U64 offset, SYMS_DwMode mode, SYMS_U64 address_size, SYMS_DwFormKind form_kind, SYMS_U64 implicit_const, SYMS_DwAttribValue *form_value_out)
Definition syms_dwarf_parser.c:558
SYMS_API SYMS_SymbolIDArray syms_dw_sid_array_from_chunk_list(SYMS_Arena *arena, SYMS_DwSymbolIDChunkList list)
Definition syms_dwarf_parser.c:409
SYMS_API SYMS_DwLineNode * syms_dw_push_line(SYMS_Arena *arena, SYMS_DwLineTableParseResult *tbl, SYMS_DwLineVMState *vm_state, SYMS_B32 start_of_sequence)
Definition syms_dwarf_parser.c:5101
SYMS_API SYMS_DwAttribValue syms_dw_attrib_value_from_form_value(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwAttribValueResolveParams resolve_params, SYMS_DwFormKind form_kind, SYMS_DwAttribClass value_class, SYMS_DwAttribValue form_value)
Definition syms_dwarf_parser.c:1909
SYMS_API SYMS_ConstInfo syms_dw_const_info_from_sid(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID id)
Definition syms_dwarf_parser.c:4509
SYMS_API SYMS_DwAttribClass syms_dw_pick_attrib_value_class(SYMS_DwLanguage lang, SYMS_DwVersion ver, SYMS_DwAttribKind attrib, SYMS_DwFormKind form_kind)
Definition syms_dwarf_parser.c:144
SYMS_API SYMS_SymbolID syms_dw_tag_ref_table_lookup_src(SYMS_DwTagRefTable table, SYMS_SymbolID dst)
Definition syms_dwarf_parser.c:3042
SYMS_API SYMS_SigInfo syms_dw_sig_info_from_handle(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SigHandle handle)
Definition syms_dwarf_parser.c:5038
SYMS_API SYMS_SymbolID syms_dw_sid_from_info_offset(SYMS_U64 info_offset)
Definition syms_dwarf_parser.c:138
SYMS_API SYMS_USID syms_dw_type_from_mem_number(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_DwMemsAccel *mems, SYMS_U64 n)
Definition syms_dwarf_parser.c:4092
SYMS_API SYMS_B32 syms_dw_sec_is_present(SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind kind)
Definition syms_dwarf_parser.c:1136
SYMS_API SYMS_String8 syms_dw_file_name_from_id(SYMS_Arena *arena, SYMS_DwUnitSetAccel *unit_set, SYMS_UnitID uid, SYMS_FileID file_id)
Definition syms_dwarf_parser.c:4849
SYMS_API SYMS_SymbolIDArray syms_dw_proc_sid_array_from_unit(SYMS_Arena *arena, SYMS_DwUnitAccel *unit)
Definition syms_dwarf_parser.c:3779
SYMS_API SYMS_DwTagStub syms_dw_cached_tag_stub_from_sid__parse_fallback(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:3692
SYMS_API SYMS_DwCompRoot syms_dw_comp_root_from_range(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_U64 index, SYMS_U64Range range)
Definition syms_dwarf_parser.c:2406
SYMS_API SYMS_U64 syms_dw_read_line_vm_header(SYMS_Arena *arena, void *line_base, SYMS_U64Range line_rng, SYMS_U64 line_off, SYMS_String8 data, SYMS_DwMode mode, SYMS_DwDbgAccel *dbg, SYMS_DwCompRoot *unit, SYMS_DwLineVMHeader *header_out)
Definition syms_dwarf_parser.c:5499
SYMS_API SYMS_DwAttribValueResolveParams syms_dw_attrib_value_resolve_params_from_comp_root(SYMS_DwCompRoot *root)
Definition syms_dwarf_parser.c:1893
SYMS_API SYMS_SymbolIDArray syms_dw_type_sid_array_from_unit(SYMS_Arena *arena, SYMS_DwUnitAccel *unit)
Definition syms_dwarf_parser.c:3791
SYMS_API SYMS_U64 syms_dw_v5_addr_from_addrs_section_base_index(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwSectionKind section, SYMS_U64 base, SYMS_U64 index)
Definition syms_dwarf_parser.c:1540
SYMS_API SYMS_String8 syms_dw_linkage_name_from_sid(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4224
SYMS_API SYMS_TypeInfo syms_dw_type_info_from_sid(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:4312
SYMS_API SYMS_U64 syms_dw_default_vbase_from_dbg(SYMS_DwDbgAccel *dbg)
Definition syms_dwarf_parser.c:1096
SYMS_API SYMS_B32 syms_dw_elf_bin_accel_is_dbg(SYMS_ElfBinAccel *bin_accel)
Definition syms_dwarf_parser.c:717
SYMS_API SYMS_String8 syms_dw_string_from_attrib_value(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwAttribValue value)
Definition syms_dwarf_parser.c:2086
SYMS_API SYMS_UnitID syms_dw_uid_from_number(SYMS_DwUnitSetAccel *accel, SYMS_U64 n)
Definition syms_dwarf_parser.c:2704
SYMS_API SYMS_USIDList syms_dw_usid_list_from_string(SYMS_Arena *arena, SYMS_DwMapAccel *map, SYMS_String8 string)
Definition syms_dwarf_parser.c:5751
SYMS_API SYMS_UnitIDAndSig syms_dw_proc_sig_handle_from_sid(SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_SymbolID sid)
Definition syms_dwarf_parser.c:5031
SYMS_API SYMS_DwTagStubList syms_dw_children_from_tag_stub(SYMS_Arena *arena, SYMS_String8 data, SYMS_DwDbgAccel *dbg, SYMS_DwUnitAccel *unit, SYMS_DwTagStub stub)
Definition syms_dwarf_parser.c:3711
SYMS_API SYMS_U64 syms_dw_file_index_from_id(SYMS_FileID id)
Definition syms_dwarf_parser.c:4837
@ SYMS_DwAbbrevKind_Tag
Definition syms_dwarf_parser.h:148
@ SYMS_DwAbbrevKind_Attrib
Definition syms_dwarf_parser.h:149
@ SYMS_DwAbbrevFlag_HasImplicitConst
Definition syms_dwarf_parser.h:158
@ SYMS_DwAbbrevFlag_HasChildren
Definition syms_dwarf_parser.h:159
@ SYMS_DwTagStubFlag_HasSpecification
Definition syms_dwarf_parser.h:322
@ SYMS_DwTagStubFlag_HasObjectPointerArg
Definition syms_dwarf_parser.h:319
@ SYMS_DwTagStubFlag_HasExternal
Definition syms_dwarf_parser.h:321
@ SYMS_DwTagStubFlag_HasLocation
Definition syms_dwarf_parser.h:320
#define SYMS_DWARF_VOID_TYPE_ID
Definition syms_dwarf_parser.h:17
SYMS_U32 SYMS_DwTagStubFlags
Definition syms_dwarf_parser.h:316
SYMS_API SYMS_String8 syms_dw_expr__transpile_to_eval(SYMS_Arena *arena, SYMS_DwDbgAccel *dbg, void *expr_base, SYMS_U64Range expr_range)
Definition syms_dwarf_transpiler.c:733
SYMS_API SYMS_U32 syms_elf_gnu_debuglink_crc32(SYMS_U32 crc, SYMS_String8 data)
Definition syms_elf.c:116
SYMS_API SYMS_U64 syms_elf_default_vbase_from_bin(SYMS_ElfBinAccel *bin)
Definition syms_elf_parser.c:479
SYMS_API SYMS_SecInfoArray syms_elf_sec_info_array_from_bin(SYMS_Arena *arena, SYMS_String8 data, SYMS_ElfBinAccel *bin)
Definition syms_elf_parser.c:466
SYMS_API SYMS_U64 syms_mach_default_vbase_from_bin(SYMS_MachBinAccel *bin)
Definition syms_mach_parser.c:448
SYMS_API SYMS_SecInfoArray syms_mach_sec_info_array_from_bin(SYMS_Arena *arena, SYMS_String8 data, SYMS_MachBinAccel *bin)
Definition syms_mach_parser.c:423
@ SYMS_FileFormat_DWARF
Definition syms_meta_base.h:100
SYMS_Arch
Definition syms_meta_base.h:6
SYMS_MemVisibility
Definition syms_meta_debug_info.h:92
@ SYMS_MemVisibility_Null
Definition syms_meta_debug_info.h:93
@ SYMS_TypeKind_Void
Definition syms_meta_debug_info.h:57
@ SYMS_TypeKind_Null
Definition syms_meta_debug_info.h:28
@ SYMS_TypeKind_Proc
Definition syms_meta_debug_info.h:75
@ SYMS_TypeKind_MemberPtr
Definition syms_meta_debug_info.h:73
@ SYMS_TypeKind_Array
Definition syms_meta_debug_info.h:74
@ SYMS_TypeKind_UInt64
Definition syms_meta_debug_info.h:41
@ SYMS_TypeKind_Ptr
Definition syms_meta_debug_info.h:70
SYMS_SymbolKind
Definition syms_meta_debug_info.h:15
@ SYMS_SymbolKind_Const
Definition syms_meta_debug_info.h:22
@ SYMS_SymbolKind_LocalVariable
Definition syms_meta_debug_info.h:20
@ SYMS_SymbolKind_Type
Definition syms_meta_debug_info.h:17
@ SYMS_SymbolKind_Procedure
Definition syms_meta_debug_info.h:18
@ SYMS_SymbolKind_Inline
Definition syms_meta_debug_info.h:24
@ SYMS_SymbolKind_ImageRelativeVariable
Definition syms_meta_debug_info.h:19
@ SYMS_SymbolKind_Null
Definition syms_meta_debug_info.h:16
@ SYMS_SymbolKind_Scope
Definition syms_meta_debug_info.h:23
@ SYMS_UnitFeature_CompilationUnit
Definition syms_meta_debug_info.h:8
@ SYMS_UnitFeature_ExternVariables
Definition syms_meta_debug_info.h:11
@ SYMS_UnitFeature_Types
Definition syms_meta_debug_info.h:9
@ SYMS_UnitFeature_Functions
Definition syms_meta_debug_info.h:12
@ SYMS_UnitFeature_StaticVariables
Definition syms_meta_debug_info.h:10
SYMS_API SYMS_Language syms_dw_base_language_from_dw_language(SYMS_DwLanguage v)
Definition syms_meta_dwarf.c:7
SYMS_API SYMS_DwAttribClass syms_dw_attrib_class_from_attrib_kind(SYMS_DwAttribKind v)
Definition syms_meta_dwarf.c:363
SYMS_API SYMS_MemVisibility syms_dw_mem_visibility_from_access(SYMS_DwAccess v)
Definition syms_meta_dwarf.c:602
SYMS_API SYMS_DwAttribClass syms_dw_attrib_class_from_form_kind(SYMS_DwFormKind v)
Definition syms_meta_dwarf.c:108
SYMS_API SYMS_CallConvention syms_dw_base_call_convention_from_dw_calling_convention(SYMS_DwCallingConvention v)
Definition syms_meta_dwarf.c:594
SYMS_DwAttribTypeEncoding
Definition syms_meta_dwarf.h:467
@ SYMS_DwAttribTypeEncoding_Null
Definition syms_meta_dwarf.h:468
SYMS_DwAccess
Definition syms_meta_dwarf.h:497
SYMS_DwTagKind
Definition syms_meta_dwarf.h:123
@ SYMS_DwTagKind_NULL
Definition syms_meta_dwarf.h:124
@ SYMS_DwTagKind_ENUMERATION_TYPE
Definition syms_meta_dwarf.h:128
@ SYMS_DwTagKind_WITH_STMT
Definition syms_meta_dwarf.h:152
@ SYMS_DwTagKind_ENUMERATOR
Definition syms_meta_dwarf.h:158
@ SYMS_DwTagKind_INHERITANCE
Definition syms_meta_dwarf.h:146
@ SYMS_DwTagKind_ARRAY_TYPE
Definition syms_meta_dwarf.h:125
@ SYMS_DwTagKind_VARIANT
Definition syms_meta_dwarf.h:143
@ SYMS_DwTagKind_PTR_TO_MEMBER_TYPE
Definition syms_meta_dwarf.h:149
@ SYMS_DwTagKind_STRUCTURE_TYPE
Definition syms_meta_dwarf.h:138
@ SYMS_DwTagKind_REFERENCE_TYPE
Definition syms_meta_dwarf.h:135
@ SYMS_DwTagKind_MODULE
Definition syms_meta_dwarf.h:148
@ SYMS_DwTagKind_TEMPLATE_TYPE_PARAMETER
Definition syms_meta_dwarf.h:165
@ SYMS_DwTagKind_DWARF_PROCEDURE
Definition syms_meta_dwarf.h:172
@ SYMS_DwTagKind_RVALUE_REFERENCE_TYPE
Definition syms_meta_dwarf.h:183
@ SYMS_DwTagKind_FORMAL_PARAMETER
Definition syms_meta_dwarf.h:129
@ SYMS_DwTagKind_POINTER_TYPE
Definition syms_meta_dwarf.h:134
@ SYMS_DwTagKind_LEXICAL_BLOCK
Definition syms_meta_dwarf.h:132
@ SYMS_DwTagKind_VARIABLE
Definition syms_meta_dwarf.h:170
@ SYMS_DwTagKind_BASE_TYPE
Definition syms_meta_dwarf.h:154
@ SYMS_DwTagKind_INLINED_SUBROUTINE
Definition syms_meta_dwarf.h:147
@ SYMS_DwTagKind_UNSPECIFIED_PARAMETERS
Definition syms_meta_dwarf.h:142
@ SYMS_DwTagKind_TEMPLATE_ALIAS
Definition syms_meta_dwarf.h:184
@ SYMS_DwTagKind_CLASS_TYPE
Definition syms_meta_dwarf.h:126
@ SYMS_DwTagKind_TYPEDEF
Definition syms_meta_dwarf.h:140
@ SYMS_DwTagKind_VOLATILE_TYPE
Definition syms_meta_dwarf.h:171
@ SYMS_DwTagKind_COMMON_INCLUSION
Definition syms_meta_dwarf.h:145
@ SYMS_DwTagKind_COMMON_BLOCK
Definition syms_meta_dwarf.h:144
@ SYMS_DwTagKind_UNION_TYPE
Definition syms_meta_dwarf.h:141
@ SYMS_DwTagKind_STRING_TYPE
Definition syms_meta_dwarf.h:137
@ SYMS_DwTagKind_SUBPROGRAM
Definition syms_meta_dwarf.h:164
@ SYMS_DwTagKind_SUBRANGE_TYPE
Definition syms_meta_dwarf.h:151
@ SYMS_DwTagKind_IMPORTED_DECLARATION
Definition syms_meta_dwarf.h:130
@ SYMS_DwTagKind_MEMBER
Definition syms_meta_dwarf.h:133
@ SYMS_DwTagKind_ACCESS_DECLARATION
Definition syms_meta_dwarf.h:153
@ SYMS_DwTagKind_SUBROUTINE_TYPE
Definition syms_meta_dwarf.h:139
@ SYMS_DwTagKind_CONST_TYPE
Definition syms_meta_dwarf.h:156
@ SYMS_DwTagKind_IMPORTED_MODULE
Definition syms_meta_dwarf.h:176
SYMS_DwMode
Definition syms_meta_dwarf.h:6
@ SYMS_DwMode_64Bit
Definition syms_meta_dwarf.h:9
@ SYMS_DwMode_32Bit
Definition syms_meta_dwarf.h:8
@ SYMS_DwMode_Null
Definition syms_meta_dwarf.h:7
SYMS_DwLocListEntryKind
Definition syms_meta_dwarf.h:520
@ SYMS_DwLocListEntryKind_StartLength
Definition syms_meta_dwarf.h:529
@ SYMS_DwLocListEntryKind_BaseAddressX
Definition syms_meta_dwarf.h:522
@ SYMS_DwLocListEntryKind_DefaultLocation
Definition syms_meta_dwarf.h:526
@ SYMS_DwLocListEntryKind_StartXLength
Definition syms_meta_dwarf.h:524
@ SYMS_DwLocListEntryKind_BaseAddress
Definition syms_meta_dwarf.h:527
@ SYMS_DwLocListEntryKind_StartEnd
Definition syms_meta_dwarf.h:528
@ SYMS_DwLocListEntryKind_OffsetPair
Definition syms_meta_dwarf.h:525
@ SYMS_DwLocListEntryKind_StartXEndX
Definition syms_meta_dwarf.h:523
@ SYMS_DwLocListEntryKind_EndOfList
Definition syms_meta_dwarf.h:521
SYMS_DwFormKind
Definition syms_meta_dwarf.h:218
@ SYMS_DwFormKind_REF_SIG8
Definition syms_meta_dwarf.h:243
@ SYMS_DwFormKind_FLAG
Definition syms_meta_dwarf.h:229
@ SYMS_DwFormKind_DATA8
Definition syms_meta_dwarf.h:224
@ SYMS_DwFormKind_LINE_STRP
Definition syms_meta_dwarf.h:249
@ SYMS_DwFormKind_DATA16
Definition syms_meta_dwarf.h:248
@ SYMS_DwFormKind_ADDRX3
Definition syms_meta_dwarf.h:260
@ SYMS_DwFormKind_REF4
Definition syms_meta_dwarf.h:236
@ SYMS_DwFormKind_STRING
Definition syms_meta_dwarf.h:225
@ SYMS_DwFormKind_BLOCK2
Definition syms_meta_dwarf.h:220
@ SYMS_DwFormKind_STRX3
Definition syms_meta_dwarf.h:256
@ SYMS_DwFormKind_EXPRLOC
Definition syms_meta_dwarf.h:241
@ SYMS_DwFormKind_STRX1
Definition syms_meta_dwarf.h:254
@ SYMS_DwFormKind_DATA2
Definition syms_meta_dwarf.h:222
@ SYMS_DwFormKind_RNGLISTX
Definition syms_meta_dwarf.h:252
@ SYMS_DwFormKind_SEC_OFFSET
Definition syms_meta_dwarf.h:240
@ SYMS_DwFormKind_DATA1
Definition syms_meta_dwarf.h:228
@ SYMS_DwFormKind_REF8
Definition syms_meta_dwarf.h:237
@ SYMS_DwFormKind_BLOCK1
Definition syms_meta_dwarf.h:227
@ SYMS_DwFormKind_ADDR
Definition syms_meta_dwarf.h:219
@ SYMS_DwFormKind_STRP
Definition syms_meta_dwarf.h:231
@ SYMS_DwFormKind_SDATA
Definition syms_meta_dwarf.h:230
@ SYMS_DwFormKind_BLOCK
Definition syms_meta_dwarf.h:226
@ SYMS_DwFormKind_STRX4
Definition syms_meta_dwarf.h:257
@ SYMS_DwFormKind_ADDRX4
Definition syms_meta_dwarf.h:261
@ SYMS_DwFormKind_UDATA
Definition syms_meta_dwarf.h:232
@ SYMS_DwFormKind_DATA4
Definition syms_meta_dwarf.h:223
@ SYMS_DwFormKind_REF_ADDR
Definition syms_meta_dwarf.h:233
@ SYMS_DwFormKind_ADDRX2
Definition syms_meta_dwarf.h:259
@ SYMS_DwFormKind_STRP_SUP
Definition syms_meta_dwarf.h:247
@ SYMS_DwFormKind_IMPLICIT_CONST
Definition syms_meta_dwarf.h:250
@ SYMS_DwFormKind_REF_SUP4
Definition syms_meta_dwarf.h:246
@ SYMS_DwFormKind_INDIRECT
Definition syms_meta_dwarf.h:239
@ SYMS_DwFormKind_BLOCK4
Definition syms_meta_dwarf.h:221
@ SYMS_DwFormKind_STRX
Definition syms_meta_dwarf.h:244
@ SYMS_DwFormKind_REF_UDATA
Definition syms_meta_dwarf.h:238
@ SYMS_DwFormKind_ADDRX1
Definition syms_meta_dwarf.h:258
@ SYMS_DwFormKind_STRX2
Definition syms_meta_dwarf.h:255
@ SYMS_DwFormKind_REF_SUP8
Definition syms_meta_dwarf.h:253
@ SYMS_DwFormKind_ADDRX
Definition syms_meta_dwarf.h:245
@ SYMS_DwFormKind_INVALID
Definition syms_meta_dwarf.h:262
@ SYMS_DwFormKind_FLAG_PRESENT
Definition syms_meta_dwarf.h:242
@ SYMS_DwFormKind_REF2
Definition syms_meta_dwarf.h:235
@ SYMS_DwFormKind_REF1
Definition syms_meta_dwarf.h:234
@ SYMS_DwFormKind_LOCLISTX
Definition syms_meta_dwarf.h:251
SYMS_DwVersion
Definition syms_meta_dwarf.h:12
@ SYMS_DwVersion_V1
Definition syms_meta_dwarf.h:14
@ SYMS_DwVersion_V2
Definition syms_meta_dwarf.h:15
@ SYMS_DwVersion_V3
Definition syms_meta_dwarf.h:16
@ SYMS_DwVersion_V5
Definition syms_meta_dwarf.h:18
@ SYMS_DwVersion_V4
Definition syms_meta_dwarf.h:17
SYMS_DwCallingConvention
Definition syms_meta_dwarf.h:489
@ SYMS_DwCallingConvention_Normal
Definition syms_meta_dwarf.h:490
@ SYMS_DwAttribClass_RNGLIST
Definition syms_meta_dwarf.h:211
@ SYMS_DwAttribClass_LOCLISTPTR
Definition syms_meta_dwarf.h:208
@ SYMS_DwAttribClass_STRING
Definition syms_meta_dwarf.h:213
@ SYMS_DwAttribClass_RNGLISTPTR
Definition syms_meta_dwarf.h:210
@ SYMS_DwAttribClass_CONST
Definition syms_meta_dwarf.h:203
@ SYMS_DwAttribClass_BLOCK
Definition syms_meta_dwarf.h:202
@ SYMS_DwAttribClass_LOCLIST
Definition syms_meta_dwarf.h:207
@ SYMS_DwAttribClass_UNDEFINED
Definition syms_meta_dwarf.h:216
@ SYMS_DwAttribClass_REFERENCE
Definition syms_meta_dwarf.h:212
@ SYMS_DwAttribClass_ADDRESS
Definition syms_meta_dwarf.h:201
@ SYMS_DwVirtuality_PureVirtual
Definition syms_meta_dwarf.h:506
@ SYMS_DwVirtuality_Virtual
Definition syms_meta_dwarf.h:505
SYMS_DwSectionKind
Definition syms_meta_dwarf.h:22
@ SYMS_DwSectionKind_Null
Definition syms_meta_dwarf.h:23
@ SYMS_DwSectionKind_Abbrev
Definition syms_meta_dwarf.h:24
@ SYMS_DwSectionKind_Info
Definition syms_meta_dwarf.h:27
@ SYMS_DwSectionKind_StrOffsets
Definition syms_meta_dwarf.h:38
@ SYMS_DwSectionKind_Ranges
Definition syms_meta_dwarf.h:33
@ SYMS_DwSectionKind_ARanges
Definition syms_meta_dwarf.h:25
@ SYMS_DwSectionKind_Addr
Definition syms_meta_dwarf.h:35
@ SYMS_DwSectionKind_Str
Definition syms_meta_dwarf.h:34
@ SYMS_DwSectionKind_Line
Definition syms_meta_dwarf.h:28
@ SYMS_DwSectionKind_LocLists
Definition syms_meta_dwarf.h:36
@ SYMS_DwSectionKind_COUNT
Definition syms_meta_dwarf.h:41
@ SYMS_DwSectionKind_PubNames
Definition syms_meta_dwarf.h:31
@ SYMS_DwSectionKind_RngLists
Definition syms_meta_dwarf.h:37
@ SYMS_DwSectionKind_LineStr
Definition syms_meta_dwarf.h:39
@ SYMS_DwSectionKind_PubTypes
Definition syms_meta_dwarf.h:32
@ SYMS_DwSectionKind_Loc
Definition syms_meta_dwarf.h:29
SYMS_DwLanguage
Definition syms_meta_dwarf.h:43
@ SYMS_DwLanguage_NULL
Definition syms_meta_dwarf.h:44
@ SYMS_DwLanguage_Rust
Definition syms_meta_dwarf.h:72
SYMS_U32 SYMS_DwAttribClass
Definition syms_meta_dwarf.h:199
@ SYMS_DwStdOpcode_COPY
Definition syms_meta_dwarf.h:92
@ SYMS_DwStdOpcode_ADVANCE_LINE
Definition syms_meta_dwarf.h:94
@ SYMS_DwStdOpcode_SET_ISA
Definition syms_meta_dwarf.h:103
@ SYMS_DwStdOpcode_SET_PROLOGUE_END
Definition syms_meta_dwarf.h:101
@ SYMS_DwStdOpcode_FIXED_ADVANCE_PC
Definition syms_meta_dwarf.h:100
@ SYMS_DwStdOpcode_SET_COLUMN
Definition syms_meta_dwarf.h:96
@ SYMS_DwStdOpcode_SET_BASIC_BLOCK
Definition syms_meta_dwarf.h:98
@ SYMS_DwStdOpcode_NEGATE_STMT
Definition syms_meta_dwarf.h:97
@ SYMS_DwStdOpcode_ADVANCE_PC
Definition syms_meta_dwarf.h:93
@ SYMS_DwStdOpcode_CONST_ADD_PC
Definition syms_meta_dwarf.h:99
@ SYMS_DwStdOpcode_SET_EPILOGUE_BEGIN
Definition syms_meta_dwarf.h:102
@ SYMS_DwStdOpcode_SET_FILE
Definition syms_meta_dwarf.h:95
@ SYMS_DwStdOpcode_EXTENDED_OPCODE
Definition syms_meta_dwarf.h:91
@ SYMS_DwExtOpcode_SET_ADDRESS
Definition syms_meta_dwarf.h:109
@ SYMS_DwExtOpcode_SET_DISCRIMINATOR
Definition syms_meta_dwarf.h:111
@ SYMS_DwExtOpcode_DEFINE_FILE
Definition syms_meta_dwarf.h:110
@ SYMS_DwExtOpcode_END_SEQUENCE
Definition syms_meta_dwarf.h:108
SYMS_DwRngListEntryKind
Definition syms_meta_dwarf.h:509
@ SYMS_DwRngListEntryKind_OffsetPair
Definition syms_meta_dwarf.h:514
@ SYMS_DwRngListEntryKind_StartEnd
Definition syms_meta_dwarf.h:516
@ SYMS_DwRngListEntryKind_BaseAddressX
Definition syms_meta_dwarf.h:511
@ SYMS_DwRngListEntryKind_StartxLength
Definition syms_meta_dwarf.h:513
@ SYMS_DwRngListEntryKind_EndOfList
Definition syms_meta_dwarf.h:510
@ SYMS_DwRngListEntryKind_BaseAddress
Definition syms_meta_dwarf.h:515
@ SYMS_DwRngListEntryKind_StartLength
Definition syms_meta_dwarf.h:517
@ SYMS_DwRngListEntryKind_StartxEndx
Definition syms_meta_dwarf.h:512
SYMS_DwAttribKind
Definition syms_meta_dwarf.h:265
@ SYMS_DwAttribKind_NAME
Definition syms_meta_dwarf.h:268
@ SYMS_DwAttribKind_VISIBILITY
Definition syms_meta_dwarf.h:279
@ SYMS_DwAttribKind_LOW_PC
Definition syms_meta_dwarf.h:274
@ SYMS_DwAttribKind_DECL_COLUMN
Definition syms_meta_dwarf.h:304
@ SYMS_DwAttribKind_DATA_BIT_OFFSET
Definition syms_meta_dwarf.h:354
@ SYMS_DwAttribKind_RANGES
Definition syms_meta_dwarf.h:332
@ SYMS_DwAttribKind_BYTE_SIZE
Definition syms_meta_dwarf.h:270
@ SYMS_DwAttribKind_RETURN_ADDR
Definition syms_meta_dwarf.h:292
@ SYMS_DwAttribKind_LOCATION
Definition syms_meta_dwarf.h:267
@ SYMS_DwAttribKind_EXTERNAL
Definition syms_meta_dwarf.h:310
@ SYMS_DwAttribKind_OBJECT_POINTER
Definition syms_meta_dwarf.h:347
@ SYMS_DwAttribKind_LANGUAGE
Definition syms_meta_dwarf.h:276
@ SYMS_DwAttribKind_VTABLE_ELEM_LOCATION
Definition syms_meta_dwarf.h:324
@ SYMS_DwAttribKind_VIRTUALITY
Definition syms_meta_dwarf.h:323
@ SYMS_DwAttribKind_CONTAINING_TYPE
Definition syms_meta_dwarf.h:285
@ SYMS_DwAttribKind_HIGH_PC
Definition syms_meta_dwarf.h:275
@ SYMS_DwAttribKind_CONST_VALUE
Definition syms_meta_dwarf.h:284
@ SYMS_DwAttribKind_DWO_NAME
Definition syms_meta_dwarf.h:364
@ SYMS_DwAttribKind_GNU_DWO_ID
Definition syms_meta_dwarf.h:408
@ SYMS_DwAttribKind_DECL_FILE
Definition syms_meta_dwarf.h:305
@ SYMS_DwAttribKind_LOCLISTS_BASE
Definition syms_meta_dwarf.h:386
@ SYMS_DwAttribKind_IDENTIFIER_CASE
Definition syms_meta_dwarf.h:313
@ SYMS_DwAttribKind_COMP_DIR
Definition syms_meta_dwarf.h:283
@ SYMS_DwAttribKind_ARR_COUNT
Definition syms_meta_dwarf.h:302
@ SYMS_DwAttribKind_ENCODING
Definition syms_meta_dwarf.h:309
@ SYMS_DwAttribKind_FRAME_BASE
Definition syms_meta_dwarf.h:311
@ SYMS_DwAttribKind_CALLING_CONVENTION
Definition syms_meta_dwarf.h:301
@ SYMS_DwAttribKind_GNU_DWO_NAME
Definition syms_meta_dwarf.h:407
@ SYMS_DwAttribKind_USE_UTF8
Definition syms_meta_dwarf.h:330
@ SYMS_DwAttribKind_ADDR_BASE
Definition syms_meta_dwarf.h:362
@ SYMS_DwAttribKind_PRODUCER
Definition syms_meta_dwarf.h:290
@ SYMS_DwAttribKind_LINKAGE_NAME
Definition syms_meta_dwarf.h:357
@ SYMS_DwAttribKind_STR_OFFSETS_BASE
Definition syms_meta_dwarf.h:361
@ SYMS_DwAttribKind_BIT_SIZE
Definition syms_meta_dwarf.h:272
@ SYMS_DwAttribKind_ABSTRACT_ORIGIN
Definition syms_meta_dwarf.h:296
@ SYMS_DwAttribKind_TYPE
Definition syms_meta_dwarf.h:320
@ SYMS_DwAttribKind_DATA_MEMBER_LOCATION
Definition syms_meta_dwarf.h:303
@ SYMS_DwAttribKind_DECL_LINE
Definition syms_meta_dwarf.h:306
@ SYMS_DwAttribKind_STMT_LIST
Definition syms_meta_dwarf.h:273
@ SYMS_DwAttribKind_RNGLISTS_BASE
Definition syms_meta_dwarf.h:363
@ SYMS_DwAttribKind_SPECIFICATION
Definition syms_meta_dwarf.h:318