/*
* 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 */
};
