|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * |
|
5 * This program is free software: you can redistribute it and/or modify |
|
6 * it under the terms of the GNU Lesser General Public License as published by |
|
7 * the Free Software Foundation, either version 3 of the License, or |
|
8 * (at your option) any later version. |
|
9 * |
|
10 * This program is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 * GNU Lesser General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU Lesser General Public License |
|
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
17 */ |
|
18 |
|
19 #include <iostream> |
|
20 #include "dwarfmanager.h" |
|
21 #include "inputfile.h" |
|
22 |
|
23 const string DwarfAbbrevManager::iAbbrevSectionName(".debug_abbrev"); |
|
24 void InfoContext::SetAbbrevOffset(size_t offset){ |
|
25 if (!iContextValid){ |
|
26 cerr << "Error: runtime error - SetAbbrevOffset called on invalid InfoContext\n"; |
|
27 exit(EXIT_FAILURE); |
|
28 } |
|
29 |
|
30 if (iAbbrevOffset == offset) |
|
31 return; |
|
32 // Save current entry (in particular the cursor value |
|
33 if (iAbbrevOffset != 0xffffffff){ |
|
34 AbbrevOffsetMap::iterator old = iMap.find(iAbbrevOffset); |
|
35 if (old != iMap.end()) |
|
36 old->second.iCursor = iAbbrevMapEntry.iCursor; |
|
37 else |
|
38 iMap[iAbbrevOffset] = iAbbrevMapEntry; |
|
39 } |
|
40 |
|
41 AbbrevOffsetMap::iterator i = iMap.find(offset); |
|
42 if (i != iMap.end()){ |
|
43 iAbbrevMapEntry = i->second; |
|
44 } else { |
|
45 AbbrevMap * newMap = new AbbrevMap; |
|
46 new (&iAbbrevMapEntry) AbbrevMapEntry(iSectionStart + offset, newMap); |
|
47 iMap[offset] = iAbbrevMapEntry; |
|
48 } |
|
49 iAbbrevOffset = offset; |
|
50 } |
|
51 |
|
52 DebugAbbrev & InfoContext::GetAbbrev(Dwarf_Word aCode){ |
|
53 AbbrevMap::iterator i = iAbbrevMapEntry.iMap->find(aCode); |
|
54 if (i != iAbbrevMapEntry.iMap->end()){ |
|
55 return i->second; |
|
56 } else { |
|
57 return FindAbbrev(aCode); |
|
58 } |
|
59 } |
|
60 |
|
61 DebugAbbrev & InfoContext::FindAbbrev(Dwarf_Word aCode){ |
|
62 // retrieve cursor for where we've scanned so far. |
|
63 Dwarf_Byte_Ptr p = iAbbrevMapEntry.iCursor; |
|
64 // NB. error if we don't find the code before section end |
|
65 Dwarf_Byte_Ptr lim = iSectionEnd; |
|
66 bool error = false; |
|
67 bool found = false; |
|
68 size_t leb128_length; |
|
69 |
|
70 while (!found && (p < lim)){ |
|
71 |
|
72 #define CHECK_ABBREV_LIM(p,l,e) { if ((p)>(l)){ e = true; break;} } |
|
73 #define CHECK_DECODE_ULEB128(v,p,n,l,e) \ |
|
74 DECODE_ULEB128(v,p,n)\ |
|
75 CHECK_ABBREV_LIM(p,l,e); |
|
76 |
|
77 size_t count = 0; |
|
78 //CHECK_DECODE_ULEB128(abbrev_code,p,leb128_length,lim, error); |
|
79 Dwarf_Word abbrev_code = DwarfSectionManager::DecodeUnsignedLeb128(p, leb128_length); |
|
80 p += leb128_length; |
|
81 if (p>lim){ |
|
82 error = true; |
|
83 break; |
|
84 } |
|
85 // Might as well error here since either we've found the NULL abbrev |
|
86 if (abbrev_code == 0) { |
|
87 DebugAbbrev abbr(0, 0, 0, NULL, NULL); |
|
88 (*iAbbrevMapEntry.iMap)[0] = abbr; |
|
89 if (aCode == 0) // ??? why would it |
|
90 found = true; |
|
91 } |
|
92 |
|
93 CHECK_DECODE_ULEB128(tag,p,leb128_length,lim, error); |
|
94 // don't care about 'has child' |
|
95 p++; |
|
96 CHECK_ABBREV_LIM(p,lim,error); |
|
97 Dwarf_Byte_Ptr raw_attr_ptr = p; |
|
98 Dwarf_Word attr; |
|
99 Dwarf_Word attr_form; |
|
100 do { |
|
101 CHECK_DECODE_ULEB128(a,p,leb128_length,lim, error); |
|
102 attr = a; |
|
103 CHECK_DECODE_ULEB128(f,p,leb128_length,lim, error); |
|
104 attr_form = f; |
|
105 |
|
106 if (attr != 0) |
|
107 count++; |
|
108 |
|
109 } while (attr != 0 || attr_form != 0); |
|
110 |
|
111 DebugAbbrevAttrForm * list = new DebugAbbrevAttrForm[count]; |
|
112 Dwarf_Byte_Ptr q=raw_attr_ptr; |
|
113 for (size_t i=0 ; i < count ; i++){ |
|
114 list[i].iAttr = ULEB128(q,leb128_length); |
|
115 list[i].iForm = ULEB128(q,leb128_length); |
|
116 } |
|
117 DebugAbbrev abbr(abbrev_code, tag, count, raw_attr_ptr, list); |
|
118 (*iAbbrevMapEntry.iMap)[abbrev_code] = abbr; |
|
119 if (abbrev_code == aCode) |
|
120 found = true; |
|
121 } |
|
122 if (error){ |
|
123 cerr << "Error: corrupt .debug_abbrev section\n"; |
|
124 exit(EXIT_FAILURE); |
|
125 } |
|
126 if (!found){ |
|
127 cerr << "Error: abbrev code not found in .debug_abbrev section\n"; |
|
128 exit(EXIT_FAILURE); |
|
129 } |
|
130 // record where we scanned to |
|
131 iAbbrevMapEntry.iCursor = p; |
|
132 // get the |
|
133 AbbrevMap::iterator i = iAbbrevMapEntry.iMap->find(aCode); |
|
134 if (i == iAbbrevMapEntry.iMap->end()){ |
|
135 cerr << "Error: Runtime error processing .debug_abbrev section\n"; |
|
136 exit(EXIT_FAILURE); |
|
137 } |
|
138 |
|
139 return i->second; |
|
140 } |
|
141 |
|
142 void DwarfAbbrevManager::StartContext(PathName & aName){ |
|
143 Dwarf_Byte_Ptr section = GetSection(aName); |
|
144 iInfoContext.Init(section, section + GetSectionSize(aName), GetSectionOffset(aName)); |
|
145 } |
|
146 |
|
147 void DwarfAbbrevManager::EndContext(){ |
|
148 iInfoContext.Reset(); |
|
149 } |
|
150 |
|
151 void DwarfAbbrevManager::SetContextAbbrevOffset(Uint32 offset){ |
|
152 iInfoContext.SetAbbrevOffset(offset); |
|
153 } |
|
154 |
|
155 size_t DwarfAbbrevManager::GetContextSectionOffset(){ |
|
156 return iInfoContext.GetSectionOffset(); |
|
157 } |
|
158 |
|
159 DebugAbbrev & DwarfAbbrevManager::GetAbbrev(Dwarf_Word aCode){ |
|
160 return iInfoContext.GetAbbrev(aCode); |
|
161 } |