xref: /haiku/src/kits/debugger/dwarf/AbbreviationTable.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
1 /*
2  * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "AbbreviationTable.h"
7 
8 #include <stdio.h>
9 
10 #include <new>
11 
12 
13 AbbreviationTable::AbbreviationTable(off_t offset)
14 	:
15 	fOffset(offset),
16 	fData(NULL),
17 	fSize(0)
18 {
19 }
20 
21 
22 AbbreviationTable::~AbbreviationTable()
23 {
24 	AbbreviationTableEntry* entry = fEntryTable.Clear(true);
25 	while (entry != NULL) {
26 		AbbreviationTableEntry* next = entry->next;
27 		delete entry;
28 		entry = next;
29 	}
30 }
31 
32 
33 status_t
34 AbbreviationTable::Init(const void* section, off_t sectionSize)
35 {
36 	if (fOffset < 0 || fOffset >= sectionSize)
37 		return B_BAD_DATA;
38 
39 	fData = (uint8*)section + fOffset;
40 	fSize = sectionSize - fOffset;
41 		// That's only the maximum size. Will be adjusted at the end.
42 
43 	status_t error = fEntryTable.Init();
44 	if (error != B_OK)
45 		return error;
46 
47 	DataReader abbrevReader(fData, fSize, 4);
48 		// address size doesn't matter here
49 
50 	while (true) {
51 		bool nullEntry;
52 		status_t error = _ParseAbbreviationEntry(abbrevReader, nullEntry);
53 		if (error != B_OK)
54 			return error;
55 
56 		if (nullEntry)
57 			break;
58 	}
59 
60 	fSize -= abbrevReader.BytesRemaining();
61 
62 	return B_OK;
63 }
64 
65 
66 bool
67 AbbreviationTable::GetAbbreviationEntry(uint32 code, AbbreviationEntry& entry)
68 {
69 	AbbreviationTableEntry* tableEntry = fEntryTable.Lookup(code);
70 	if (tableEntry == NULL)
71 		return false;
72 
73 	entry.SetTo(code, fData + tableEntry->offset, tableEntry->size);
74 	return true;
75 }
76 
77 
78 status_t
79 AbbreviationTable::_ParseAbbreviationEntry(DataReader& abbrevReader,
80 	bool& _nullEntry)
81 {
82 	uint32 code = abbrevReader.ReadUnsignedLEB128(0);
83 	if (code == 0) {
84 		if (abbrevReader.HasOverflow()) {
85 			fprintf(stderr, "Invalid abbreviation table 1!\n");
86 			return B_BAD_DATA;
87 		}
88 		_nullEntry = true;
89 		return B_OK;
90 	}
91 
92 	off_t remaining = abbrevReader.BytesRemaining();
93 
94 /*	uint32 tag =*/ abbrevReader.ReadUnsignedLEB128(0);
95 /*	uint8 hasChildren =*/ abbrevReader.Read<uint8>(DW_CHILDREN_no);
96 
97 //	printf("entry: %" B_PRIu32 ", tag: %" B_PRIu32 ", children: %d\n", code, tag,
98 //		hasChildren);
99 
100 	// parse attribute specifications
101 	while (true) {
102 		uint32 attributeName = abbrevReader.ReadUnsignedLEB128(0);
103 		uint32 attributeForm = abbrevReader.ReadUnsignedLEB128(0);
104 		if (abbrevReader.HasOverflow()) {
105 			fprintf(stderr, "Invalid abbreviation table 2!\n");
106 			return B_BAD_DATA;
107 		}
108 
109 		if (attributeName == 0 && attributeForm == 0)
110 			break;
111 
112 		if (attributeForm == DW_FORM_implicit_const)
113 			abbrevReader.ReadSignedLEB128(0);
114 
115 //		printf("  attr: name: %" B_PRIu32 ", form: %" B_PRIu32 "\n", attributeName,
116 //			attributeForm);
117 	}
118 
119 	// create the entry
120 	if (fEntryTable.Lookup(code) == NULL) {
121 		AbbreviationTableEntry* entry = new(std::nothrow)
122 			AbbreviationTableEntry(code, fSize - remaining,
123 				remaining - abbrevReader.BytesRemaining());
124 		if (entry == NULL)
125 			return B_NO_MEMORY;
126 
127 		fEntryTable.Insert(entry);
128 	} else {
129 		fprintf(stderr, "Duplicate abbreviation table entry %" B_PRIu32 "!\n",
130 			code);
131 	}
132 
133 	_nullEntry = false;
134 	return B_OK;
135 }
136