tools/elf4rom/src/dwarfabbrevmanager.cpp
changeset 34 92d87f2e53c2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/elf4rom/src/dwarfabbrevmanager.cpp	Fri Jan 15 09:07:44 2010 +0000
@@ -0,0 +1,161 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU Lesser General Public License for more details.
+* 
+* You should have received a copy of the GNU Lesser General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <iostream>
+#include "dwarfmanager.h"
+#include "inputfile.h"
+
+const string DwarfAbbrevManager::iAbbrevSectionName(".debug_abbrev");
+void InfoContext::SetAbbrevOffset(size_t offset){
+	if (!iContextValid){
+		cerr << "Error: runtime error - SetAbbrevOffset called on invalid InfoContext\n";
+		exit(EXIT_FAILURE);
+	}
+	
+	if (iAbbrevOffset == offset)
+			return;
+	// Save current entry (in particular the cursor value
+	if (iAbbrevOffset != 0xffffffff){
+		AbbrevOffsetMap::iterator old = iMap.find(iAbbrevOffset);
+		if (old != iMap.end())
+			old->second.iCursor = iAbbrevMapEntry.iCursor;
+		else
+			iMap[iAbbrevOffset] = iAbbrevMapEntry;
+	}
+	
+	AbbrevOffsetMap::iterator i = iMap.find(offset);
+	if (i != iMap.end()){
+		iAbbrevMapEntry = i->second;
+	} else {
+		AbbrevMap * newMap = new AbbrevMap;
+		new (&iAbbrevMapEntry) AbbrevMapEntry(iSectionStart + offset, newMap);
+		iMap[offset] = iAbbrevMapEntry;
+	}
+	iAbbrevOffset = offset;
+}
+
+DebugAbbrev & InfoContext::GetAbbrev(Dwarf_Word aCode){
+	AbbrevMap::iterator i = iAbbrevMapEntry.iMap->find(aCode);
+	if (i != iAbbrevMapEntry.iMap->end()){
+			return i->second;
+	} else {
+		return FindAbbrev(aCode);
+	}
+}
+
+DebugAbbrev & InfoContext::FindAbbrev(Dwarf_Word aCode){
+	// retrieve cursor for where we've scanned so far.
+	Dwarf_Byte_Ptr p = iAbbrevMapEntry.iCursor;
+	// NB. error if we don't find the code before section end
+	Dwarf_Byte_Ptr lim = iSectionEnd;
+	bool error = false;
+	bool found = false;
+	size_t leb128_length;
+
+	while (!found && (p < lim)){
+		
+#define CHECK_ABBREV_LIM(p,l,e) { if ((p)>(l)){ e = true; break;} }
+#define CHECK_DECODE_ULEB128(v,p,n,l,e) \
+			DECODE_ULEB128(v,p,n)\
+			CHECK_ABBREV_LIM(p,l,e);
+		
+		size_t count = 0;
+		//CHECK_DECODE_ULEB128(abbrev_code,p,leb128_length,lim, error);
+		Dwarf_Word abbrev_code = DwarfSectionManager::DecodeUnsignedLeb128(p, leb128_length);
+		p += leb128_length;
+		if (p>lim){ 
+			error = true; 
+			break;
+		}
+		// Might as well error here since either we've found the NULL abbrev
+	    if (abbrev_code == 0) {
+	    	DebugAbbrev abbr(0, 0, 0, NULL, NULL);
+	    	(*iAbbrevMapEntry.iMap)[0] = abbr;
+	    	if (aCode == 0) // ??? why would it
+	    		found = true;
+	    }
+
+		CHECK_DECODE_ULEB128(tag,p,leb128_length,lim, error);
+		// don't care about 'has child'
+	    p++;
+	    CHECK_ABBREV_LIM(p,lim,error);
+	    Dwarf_Byte_Ptr raw_attr_ptr = p;
+	    Dwarf_Word attr;
+	    Dwarf_Word attr_form;
+	    do {
+	    	CHECK_DECODE_ULEB128(a,p,leb128_length,lim, error);
+	    	attr = a;
+	    	CHECK_DECODE_ULEB128(f,p,leb128_length,lim, error);
+	    	attr_form = f;
+
+	    	if (attr != 0)
+	    		count++;
+
+	    } while (attr != 0 || attr_form != 0);
+	    
+		DebugAbbrevAttrForm * list = new DebugAbbrevAttrForm[count];
+		Dwarf_Byte_Ptr q=raw_attr_ptr;
+		for (size_t i=0 ; i < count ; i++){
+			list[i].iAttr = ULEB128(q,leb128_length);
+			list[i].iForm = ULEB128(q,leb128_length);
+		}
+	    DebugAbbrev abbr(abbrev_code, tag, count, raw_attr_ptr, list);
+	    (*iAbbrevMapEntry.iMap)[abbrev_code] = abbr;
+	    if (abbrev_code == aCode)
+	    	found = true;
+	}
+	if (error){
+		cerr << "Error: corrupt .debug_abbrev section\n";
+		exit(EXIT_FAILURE);
+	}
+	if (!found){
+		cerr << "Error: abbrev code not found in .debug_abbrev section\n";
+		exit(EXIT_FAILURE);
+	}
+	// record where we scanned to
+	iAbbrevMapEntry.iCursor = p;
+	// get the 
+	AbbrevMap::iterator i = iAbbrevMapEntry.iMap->find(aCode);
+	if (i == iAbbrevMapEntry.iMap->end()){
+		cerr << "Error: Runtime error processing .debug_abbrev section\n";
+		exit(EXIT_FAILURE);
+	} 
+
+	return i->second;
+}
+
+void DwarfAbbrevManager::StartContext(PathName & aName){
+	Dwarf_Byte_Ptr section = GetSection(aName);
+	iInfoContext.Init(section, section + GetSectionSize(aName), GetSectionOffset(aName));
+}
+
+void DwarfAbbrevManager::EndContext(){
+	iInfoContext.Reset();
+}
+
+void DwarfAbbrevManager::SetContextAbbrevOffset(Uint32 offset){
+	iInfoContext.SetAbbrevOffset(offset);
+}
+
+size_t DwarfAbbrevManager::GetContextSectionOffset(){
+	return iInfoContext.GetSectionOffset();
+}
+
+DebugAbbrev & DwarfAbbrevManager::GetAbbrev(Dwarf_Word aCode){
+	return iInfoContext.GetAbbrev(aCode);
+}