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
AbbreviationTable(off_t offset)13 AbbreviationTable::AbbreviationTable(off_t offset)
14 :
15 fOffset(offset),
16 fData(NULL),
17 fSize(0)
18 {
19 }
20
21
~AbbreviationTable()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
Init(const void * section,off_t sectionSize)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, false);
48 // address size and endianness don'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
GetAbbreviationEntry(uint32 code,AbbreviationEntry & entry)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
_ParseAbbreviationEntry(DataReader & abbrevReader,bool & _nullEntry)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