tools/elf4rom/src/dwarfinfomanager.cpp
author johnathan.white@2718R8BGH51.accenture.com
Mon, 08 Mar 2010 18:45:03 +0000
changeset 46 b6935a90ca64
parent 34 92d87f2e53c2
permissions -rwxr-xr-x
Modify framebuffer and NGA framebuffer to read screen size from board model dtb file. Optimise memory usuage of frame buffer Add example minigui application with hooks to profiler (which writes results to S:\). Modified NGA framebuffer to run its own dfc queue at high priority

/*
* 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 <string.h>
#include <iostream>
#include <cassert>

#include "dwarfmanager.h"
#include "inputfile.h"

const string DwarfInfoManager::iInfoSectionName(".debug_info");

void DwarfInfoManager::ProcessSection(FileShdrPair & aPair, Dwarf_Byte_Ptr aStart, Dwarf_Byte_Ptr aEnd){
	iDwarfAbbrevManager.StartContext(aPair.iXIPFileDetails.iElfFile);
	Dwarf_Byte_Ptr p = aStart;
	Dwarf_Byte_Ptr e = aEnd;
	while (p < e) {
		p = ProcessCU(aPair, p, e);
	}
	iDwarfAbbrevManager.EndContext();
}

#define READ_DWARF_VAL(v,t,p) t v = *((t *)p); p += sizeof(t);
Dwarf_Byte_Ptr DwarfInfoManager::ProcessCU(FileShdrPair & aPair, Dwarf_Byte_Ptr s, Dwarf_Byte_Ptr e){
	Dwarf_Byte_Ptr p = s;
	//Read the CU header info
	// first check whether we're dealing with 32bit or 64 bit DWARF
	
	// TODO: must abstract over base types e.g uint32 etc.
	// TODO: this might not be 4 byte aligned and so could cause problems on some
	// architectures
	READ_DWARF_VAL(len, Uint32, p);
	if (len >= 0xfffffff0u){
		cerr << "Error: 64 bit DWARF not supported\n";
		exit(EXIT_FAILURE);
	}
	iLocalLength = len;
	Dwarf_Byte_Ptr end = p + len;
	// TODO: make sensitive to dwarf version number?
	READ_DWARF_VAL(version, Dwarf_Half, p);
	Uint32 abbrevOffset = *((Uint32 *)p);
	// update the offset into the abbrev table
	*((Uint32 *)p) = (Uint32)(abbrevOffset + iDwarfAbbrevManager.GetContextSectionOffset());
	p += sizeof(Uint32);
	READ_DWARF_VAL(address_size, Byte, p);
	
	// TODO: if this isn't 4 we're doomed aren't we?
	iAddressSize = address_size;
	
	iDwarfAbbrevManager.SetContextAbbrevOffset(abbrevOffset);
	
	// now process each DIE until end.
	while (p < end) {
		p = ProcessDIE(aPair, p, end);
	}

	return p;
}

void NoteProducer(FileShdrPair & aPair, Dwarf_Byte_Ptr aPtr, Dwarf_Unsigned aForm){

	switch (aForm){
	case DW_FORM_string:{
		const char * producer = (const char *)aPtr;
		const char * RvctProducer = "ARM/Thumb C/C++ Compiler, RVCT";
		const size_t RvctProducerLength = strlen(RvctProducer);
		const char * GccProducer = "GNU C++";
		const size_t GccProducerLength = strlen(GccProducer);
		if (!strncmp(producer, RvctProducer, RvctProducerLength))
			aPair.iXIPFileDetails.iRVCTProduced = true;
		if (!strncmp(producer, GccProducer, GccProducerLength))
			aPair.iXIPFileDetails.iGCCProduced = true;		
		return;
	}
    case DW_FORM_indirect: {
	    size_t indir_len = 0;
	    Dwarf_Unsigned form_indirect = DwarfSectionManager::DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen, will get warned later */
	    	return;
	    }
	    return NoteProducer(aPair, aPtr+indir_len, form_indirect);
		}
    case DW_FORM_strp:
    	// TODO - We need to get the string table for this -- 
    	return;
	}
}

Dwarf_Byte_Ptr DwarfInfoManager::ProcessDIE(FileShdrPair & aPair, Dwarf_Byte_Ptr s, Dwarf_Byte_Ptr e){
	Dwarf_Byte_Ptr info_ptr = s;
    size_t leb128_length;
    
    Dwarf_Word abbrev_code = DecodeUnsignedLeb128(info_ptr, leb128_length);
    info_ptr += leb128_length;
    if (abbrev_code == 0) {
    	return info_ptr;
    }

    DebugAbbrev & abbrev = iDwarfAbbrevManager.GetAbbrev(abbrev_code);
 
    //cout << "Tag = " << GetDwarfTag(abbrev.iTag) << " Code = " << abbrev_code <<  " num attrs = " << abbrev.iCount << endl;
   
    for (size_t i = 0; i < abbrev.iCount; i++){
    	size_t attr = abbrev.iParsed[i].iAttr;
    	Dwarf_Unsigned form = abbrev.iParsed[i].iForm;
    	//cout << "\tAttr " << GetDwarfAttr(attr) << " Form " << GetDwarfForm(form) << "\n";
    	
    	// record anything interesting about the producer here.
    	if (attr == DW_AT_producer)
    		NoteProducer(aPair, info_ptr, form);

    	if (attr > DW_AT_recursive)
    		info_ptr = DefaultInfoEditFn(*this, info_ptr, form, aPair);
    	else
    		info_ptr = iInfoEditFn[attr](*this, info_ptr, form, aPair);
    }
    
	return info_ptr;
}


size_t DwarfInfoManager::SizeOfDieValue(Dwarf_Half aForm, Dwarf_Byte_Ptr aPtr){
    Dwarf_Unsigned length = 0;
    size_t leb128_length = 0;
    size_t ret_value = 0;

    switch (aForm) {

    default:			/* Handles form = 0. */
    	return (aForm);

    case DW_FORM_addr:
    	return iAddressSize;

    case DW_FORM_ref_addr:
    	// TODO: sort this out
    	return 4;  // this is a 4 byte relocatable in 32 bit dwarf and 8-byte in 64 bit dwarf

    case DW_FORM_block1:
    	return (*aPtr) + 1;

    case DW_FORM_block2:
    	ret_value = READ_UNALIGNED2(aPtr) + 2;
		return ret_value;

    case DW_FORM_block4:
    	ret_value = READ_UNALIGNED4(aPtr) + 4;
    	return ret_value;

    case DW_FORM_data1:
	return 1;

    case DW_FORM_data2:
	return 2;

    case DW_FORM_data4:
	return 4;

    case DW_FORM_data8:
	return 8;

    case DW_FORM_string:
	return (strlen((char *) aPtr) + 1);

    case DW_FORM_block:
    	length = DecodeUnsignedLeb128(aPtr, leb128_length);
    	return length + leb128_length;

    case DW_FORM_flag:
	return 1;

    case DW_FORM_ref_udata:
    	DecodeUnsignedLeb128(aPtr, leb128_length);
	return leb128_length;

    case DW_FORM_indirect: {
	    size_t indir_len = 0;
	    Dwarf_Unsigned form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen */
	    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
	    }
	    return indir_len + SizeOfDieValue(form_indirect, aPtr+indir_len);
	}

    case DW_FORM_ref1:
    	return 1;

    case DW_FORM_ref2:
    	return 2;

    case DW_FORM_ref4:
    	return 4;

    case DW_FORM_ref8:
    	return 8;

    case DW_FORM_sdata:
    	DecodeSignedLeb128(aPtr, leb128_length);
    	return leb128_length;

    case DW_FORM_strp:
    	// TODO: sort this out
    	return 4;  // this is a 4 byte relocatable in 32 bit dwarf and 8-byte in 64 bit dwarf

    case DW_FORM_udata:
    	DecodeUnsignedLeb128(aPtr, leb128_length);
    	return leb128_length;
    }
}

Dwarf_Byte_Ptr DwarfInfoManager::DefaultInfoEditFn(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	return aPtr + aManager.SizeOfDieValue(aForm, aPtr);
}

Dwarf_Byte_Ptr DwarfInfoManager::ErrorInfoEditFn(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	cerr << "Error: Undefined DW_FORM value: " << aForm << "\n" ;
	exit(EXIT_FAILURE);
	return aPtr;
}

// TODO: implicitly only deals with 32-bit DWARF
// Called from other edit functions to deal with blocks that contain location expressions.
Dwarf_Byte_Ptr DwarfInfoManager::InfoEditLocExpr(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	Dwarf_Unsigned length = 0;
	bool locExpr = false;
	Dwarf_Byte_Ptr block = aPtr;
	if (aForm == DW_FORM_block1) {
		locExpr = true;
		length = block[0];
		block++;
		aPtr += (length + 1); 
	} else if (aForm == DW_FORM_block2) {
		locExpr = true;
		length = READ_UNALIGNED2(block);
		block += 2;
		aPtr += (length + 2); 
	} else if (aForm == DW_FORM_block4) {
		locExpr = true;
		length = READ_UNALIGNED4(block);
		block += 4;
		aPtr += (length + 4); 
	} else if (aForm == DW_FORM_block) {
		locExpr = true;
		size_t leb_length = 0;
		length = DecodeUnsignedLeb128(block, leb_length);
		block += leb_length;
		aPtr += (length + leb_length); 
	}

	if (locExpr){		
		EditLocationExpression (block, aManager.iAddressSize, length, aPair);
		return aPtr;
	} else if (aForm == DW_FORM_indirect){
	    size_t indir_len = 0;
	    Dwarf_Half form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen */
	    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
	    }
	    return InfoEditLocExpr(aManager, aPtr+indir_len, form_indirect, aPair);
	
	} else
		return aPtr + aManager.SizeOfDieValue(aForm, aPtr);
}
// TODO: implicitly only deals with 32-bit DWARF
Dwarf_Byte_Ptr DwarfInfoManager::InfoEditAddress(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	if (aForm == DW_FORM_addr){
		LinearAddr addr = READ_UNALIGNED4(aPtr);
		LinearAddr relocatedAddr = aPair.iXIPFileDetails.Relocate(addr);
		WRITE_UNALIGNED4(aPtr, relocatedAddr);
		return aPtr + 4;
	} else if (aForm == DW_FORM_indirect){
	    size_t indir_len = 0;
	    Dwarf_Unsigned form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen */
	    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
	    }
	    return InfoEditAddress(aManager, aPtr+indir_len, form_indirect, aPair);
	
	} else
		return aPtr + aManager.SizeOfDieValue(aForm, aPtr);
}

// TODO: implicitly only deals with 32-bit DWARF
Dwarf_Byte_Ptr DwarfInfoManager::InfoEditLinePtr(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	if (aForm == DW_FORM_data4){
		size_t offset = READ_UNALIGNED4(aPtr);
		size_t newOffset = aManager.iDwarfManager.GetLineSectionOffset(aPair.iXIPFileDetails.iElfFile) + offset;
		if (offset != newOffset)
			WRITE_UNALIGNED4(aPtr, newOffset);
		return aPtr + 4;
	} else if (aForm == DW_FORM_indirect){
	    size_t indir_len = 0;
	    Dwarf_Half form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen */
	    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
	    }
	    return InfoEditLinePtr(aManager, aPtr+indir_len, form_indirect, aPair);
	
	} else
		return aPtr + aManager.SizeOfDieValue(aForm, aPtr);
}

// TODO: implicitly only deals with 32-bit DWARF
Dwarf_Byte_Ptr DwarfInfoManager::InfoEditLocListPtr(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	if (aForm == DW_FORM_data4){
		size_t offset = READ_UNALIGNED4(aPtr);
		size_t newOffset = aManager.iDwarfManager.GetLocListSectionOffset(aPair.iXIPFileDetails.iElfFile) + offset;
		if (offset != newOffset)
			WRITE_UNALIGNED4(aPtr, newOffset);
		return aPtr + 4;
	} else if (aForm == DW_FORM_indirect){
	    size_t indir_len = 0;
	    Dwarf_Half form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen */
	    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
	    }
	    return InfoEditLocListPtr(aManager, aPtr+indir_len, form_indirect, aPair);
	
	} else
		//return aPtr + aManager.SizeOfDieValue(aForm, aPtr);
		return InfoEditLocExpr(aManager, aPtr, aForm, aPair);
}





// TODO: implicitly only deals with 32-bit DWARF
Dwarf_Byte_Ptr DwarfInfoManager::InfoEditMacInfoPtr(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	if (aForm == DW_FORM_data4){
		size_t offset = READ_UNALIGNED4(aPtr);
		size_t newOffset = aManager.iDwarfManager.GetMacInfoSectionOffset(aPair.iXIPFileDetails.iElfFile) + offset;
		if (offset != newOffset)
			WRITE_UNALIGNED4(aPtr, newOffset);
		return aPtr + 4;
	} else if (aForm == DW_FORM_indirect){
	    size_t indir_len = 0;
	    Dwarf_Half form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen */
	    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
	    }
	    return InfoEditMacInfoPtr(aManager, aPtr+indir_len, form_indirect, aPair);
	
	} else
		return aPtr + aManager.SizeOfDieValue(aForm, aPtr);
}

// TODO: implicitly only deals with 32-bit DWARF
Dwarf_Byte_Ptr DwarfInfoManager::InfoEditRangeListPtr(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	if (aForm == DW_FORM_data4){
		size_t offset = READ_UNALIGNED4(aPtr);
		size_t newOffset = aManager.iDwarfManager.GetRangesSectionOffset(aPair.iXIPFileDetails.iElfFile) + offset;
		if (offset != newOffset)
			WRITE_UNALIGNED4(aPtr, newOffset);
		return aPtr + 4;
	} else if (aForm == DW_FORM_indirect){
	    size_t indir_len = 0;
	    Dwarf_Half form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen */
	    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
	    }
	    return InfoEditRangeListPtr(aManager, aPtr+indir_len, form_indirect, aPair);
	
	} else
		return aPtr + aManager.SizeOfDieValue(aForm, aPtr);
}

// TODO: implicitly only deals with 32-bit DWARF
Dwarf_Byte_Ptr DwarfInfoManager::InfoEditString(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	
	if (aForm == DW_FORM_strp){
		size_t offset = READ_UNALIGNED4(aPtr);
		size_t newOffset = aManager.iDwarfManager.GetStrSectionOffset(aPair.iXIPFileDetails.iElfFile) + offset;
		if (offset != newOffset)
			WRITE_UNALIGNED4(aPtr, newOffset);
		return aPtr + 4;
	} else if (aForm == DW_FORM_indirect){
	    size_t indir_len = 0;
	    Dwarf_Half form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen */
	    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
	    }
	    return InfoEditString(aManager, aPtr+indir_len, form_indirect, aPair);
	
	} else
		return aPtr + aManager.SizeOfDieValue(aForm, aPtr);
}

// TODO: implicitly only deals with 32-bit DWARF
Dwarf_Byte_Ptr DwarfInfoManager::InfoEditReference(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	if (aForm == DW_FORM_ref_addr){
		size_t offset = READ_UNALIGNED4(aPtr);
		size_t newOffset = aManager.CheckNewOffset(aManager.GetSectionOffset(aPair.iXIPFileDetails.iElfFile), offset);
		if (offset != newOffset)
			WRITE_UNALIGNED4(aPtr, newOffset);
		return aPtr + 4;
	} else if (aForm == DW_FORM_indirect){
	    size_t indir_len = 0;
	    Dwarf_Half form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
	    if (form_indirect == DW_FORM_indirect) {
			/* 	Eek, should never happen */
	    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
	    }
	    return InfoEditReference(aManager, aPtr+indir_len, form_indirect, aPair);
	
	} else
		//return aPtr + aManager.SizeOfDieValue(aForm, aPtr);
		return InfoEditLocExpr(aManager, aPtr, aForm, aPair);
}

// TODO: implicitly only deals with 32-bit DWARF
// Explicitly check for *_address and *_strp then let the reference handler deal with the flag possiblity as s 'else'. 
Dwarf_Byte_Ptr DwarfInfoManager::InfoEditTrampoline(DwarfInfoManager& aManager, Dwarf_Byte_Ptr aPtr, Dwarf_Half aForm, FileShdrPair & aPair){
	if (aForm == DW_FORM_addr)
		return InfoEditAddress(aManager, aPtr, aForm, aPair);
	else if (aForm = DW_FORM_strp)
		return InfoEditString(aManager, aPtr, aForm, aPair);
	else if (aForm == DW_FORM_indirect){
		    size_t indir_len = 0;
		    Dwarf_Half form_indirect = DecodeUnsignedLeb128(aPtr, indir_len);
		    if (form_indirect == DW_FORM_indirect) {
				/* 	Eek, should never happen */
		    	cerr << "Error: DW_FORM_indirect gone recursive! Can't happen\n";
		    }
		    return InfoEditTrampoline(aManager, aPtr+indir_len, form_indirect, aPair);
		
		} 
	else
		return InfoEditReference(aManager, aPtr, aForm, aPair);
}


DwarfInfoManager::InfoEditFn DwarfInfoManager::iInfoEditFn [] = {
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0 so this should never be called
	DwarfInfoManager::InfoEditReference, 	// DW_AT_sibling                           0x01
	DwarfInfoManager::InfoEditLocListPtr, 	// DW_AT_location                          0x02
	DwarfInfoManager::InfoEditString, 		// DW_AT_name                              0x03
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  4 so this should never be called
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  5 so this should never be called
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  6 so this should never be called
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  7 so this should never be called
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  8 so this should never be called
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_ordering                          0x09
    // TODO: This doesn't appear in the DWARF 3 spec of 2005/12/05 :-( so just defualt it for now
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_subscr_data                       0x0a
    DwarfInfoManager::InfoEditReference, 	// DW_AT_byte_size                         0x0b
    DwarfInfoManager::InfoEditReference, 	// DW_AT_bit_offset                        0x0c
    DwarfInfoManager::InfoEditReference, 	// DW_AT_bit_size                          0x0d
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x0e so this should never be called
    // TODO: This doesn't appear in the DWARF 3 spec of 2005/12/05 :-( so just defualt it for now
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_element_list                      0x0f
    DwarfInfoManager::InfoEditLinePtr, 		// DW_AT_stmt_list                         0x10
    DwarfInfoManager::InfoEditAddress, 		// DW_AT_low_pc                            0x11
    DwarfInfoManager::InfoEditAddress, 		// DW_AT_high_pc                           0x12
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_language                          0x13
    // TODO: This doesn't appear in the DWARF 3 spec of 2005/12/05 :-( so just defualt it for now
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_member                            0x14
    DwarfInfoManager::InfoEditReference, 	// DW_AT_discr                             0x15
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_discr_value                       0x16
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_visibility                        0x17
    DwarfInfoManager::InfoEditReference, 	// DW_AT_import                            0x18
    DwarfInfoManager::InfoEditLocListPtr, 	// DW_AT_string_length                     0x19
    DwarfInfoManager::InfoEditReference, 	// DW_AT_common_reference                  0x1a
    DwarfInfoManager::InfoEditString, 		// DW_AT_comp_dir                          0x1b
    DwarfInfoManager::InfoEditString, 		// DW_AT_const_value                       0x1c
    DwarfInfoManager::InfoEditReference, 	// DW_AT_containing_type                   0x1d
    DwarfInfoManager::InfoEditReference, 	// DW_AT_default_value                     0x1e
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x1f so this should never be called
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_inline                            0x20
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_is_optional                       0x21
    DwarfInfoManager::InfoEditReference, 	// DW_AT_lower_bound                       0x22
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x23 so this should never be called
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x24 so this should never be called
    DwarfInfoManager::InfoEditString, 		// DW_AT_producer                          0x25
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x26 so this should never be called
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_prototyped                        0x27
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x28 so this should never be called
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x29 so this should never be called
    DwarfInfoManager::InfoEditLocListPtr, 	// DW_AT_return_addr                       0x2a
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x2b so this should never be called
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_start_scope                       0x2c
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x2d so this should never be called
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_bit_stride                        0x2e /* DWARF3 name */
    DwarfInfoManager::InfoEditReference, 	// DW_AT_upper_bound                       0x2f
	DwarfInfoManager::ErrorInfoEditFn, 		// There is no DW_FORM  0x30 so this should never be called
    DwarfInfoManager::InfoEditReference, 	// DW_AT_abstract_origin                   0x31
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_accessibility                     0x32
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_address_class                     0x33
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_artificial                        0x34
    DwarfInfoManager::InfoEditReference, 	// DW_AT_base_types                        0x35
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_calling_convention                0x36
    DwarfInfoManager::InfoEditReference, 	// DW_AT_count                             0x37
    DwarfInfoManager::InfoEditLocListPtr, 	// DW_AT_data_member_location              0x38
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_decl_column                       0x39
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_decl_file                         0x3a
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_decl_line                         0x3b
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_declaration                       0x3c
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_discr_list                        0x3d
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_encoding                          0x3e
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_external                          0x3f
    DwarfInfoManager::InfoEditLocListPtr, 	// DW_AT_frame_base                        0x40
    DwarfInfoManager::InfoEditReference, 	// DW_AT_friend                            0x41
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_identifier_case                   0x42
    DwarfInfoManager::InfoEditMacInfoPtr, 	// DW_AT_macro_info                        0x43
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_namelist_item                     0x44
    DwarfInfoManager::InfoEditReference, 	// DW_AT_priority                          0x45
    DwarfInfoManager::InfoEditLocListPtr, 	// DW_AT_segment                           0x46
    DwarfInfoManager::InfoEditReference, 	// DW_AT_specification                     0x47
    DwarfInfoManager::InfoEditLocListPtr, 	// DW_AT_static_link                       0x48
    DwarfInfoManager::InfoEditReference, 	// DW_AT_type                              0x49
    DwarfInfoManager::InfoEditLocListPtr, 	// DW_AT_use_location                      0x4a
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_variable_parameter                0x4b
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_virtuality                        0x4c
    DwarfInfoManager::InfoEditLocListPtr, 	// DW_AT_vtable_elem_location              0x4d
    DwarfInfoManager::InfoEditReference, 	// DW_AT_allocated                         0x4e /* DWARF3 */
    DwarfInfoManager::InfoEditReference, 	// DW_AT_associated                        0x4f /* DWARF3 */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_data_location                     0x50 /* DWARF3 */
    DwarfInfoManager::InfoEditReference, 	// DW_AT_byte_stride                       0x51 /* DWARF3f */
    DwarfInfoManager::InfoEditAddress, 		// DW_AT_entry_pc                          0x52 /* DWARF3 */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_use_UTF8                          0x53 /* DWARF3 */
    DwarfInfoManager::InfoEditReference, 	// DW_AT_extension                         0x54 /* DWARF3 */
    DwarfInfoManager::InfoEditRangeListPtr, // DW_AT_ranges                            0x55 /* DWARF3 */
    DwarfInfoManager::InfoEditTrampoline, 	// DW_AT_trampoline                        0x56 /* DWARF3 */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_call_column                       0x57 /* DWARF3 */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_call_file                         0x58 /* DWARF3 */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_call_line                         0x59 /* DWARF3 */
    DwarfInfoManager::InfoEditString, 		// DW_AT_description                       0x5a /* DWARF3 */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_binary_scale                      0x5b /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_decimal_scale                     0x5c /* DWARF3f */
    DwarfInfoManager::InfoEditReference, 	// DW_AT_small                             0x5d /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_decimal_sign                      0x5e /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_digit_count                       0x5f /* DWARF3f */
    DwarfInfoManager::InfoEditString, 		// DW_AT_picture_string                    0x60 /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_mutable                           0x61 /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_threads_scaled                    0x62 /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_explicit                          0x63 /* DWARF3f */
    DwarfInfoManager::InfoEditReference, 	// DW_AT_object_pointer                    0x64 /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_endianity                         0x65 /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_elemental                         0x66 /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_pure                              0x67 /* DWARF3f */
    DwarfInfoManager::DefaultInfoEditFn, 	// DW_AT_recursive                         0x68 /* DWARF3f */
};