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