diff -r 1af5c1be89f8 -r 92d87f2e53c2 tools/elf4rom/src/dwarflinemanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/elf4rom/src/dwarflinemanager.cpp Fri Jan 15 09:07:44 2010 +0000 @@ -0,0 +1,185 @@ +/* +* 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 . +*/ + +#include +#include "dwarfmanager.h" +#include "inputfile.h" + +const string DwarfLineManager::iLineSectionName(".debug_line"); + +inline static size_t process_extended_line_op (FileShdrPair & aPair, Dwarf_Byte_Ptr data) +{ + size_t bytes_read; + size_t len = (size_t)ULEB128(data, bytes_read); + + if (len == 0){ + cerr << "badly formed extended line op encountered!\n"; + // a length of 0 indicates a badly formed op and will force everything to be ignored until 'end_of_sequence'. + return 0; + } + + len += bytes_read; + unsigned char op_code = *data++; + switch (op_code){ + case DW_LNE_end_sequence: + break; + case DW_LNE_set_address: { + size_t size = len - bytes_read - 1; + LinearAddr addr = GetValue(data, size); + LinearAddr relocatedAddress = aPair.iXIPFileDetails.Relocate(addr); + if (addr != relocatedAddress) + WriteValue(data, relocatedAddress, size); + break; + } + case DW_LNE_define_file: + ULEB128(data, bytes_read); + ULEB128(data, bytes_read); + ULEB128(data, bytes_read); + break; + default: + + break; + } + + return len; +} + +void DwarfLineManager::ProcessSection(FileShdrPair & aPair, Dwarf_Byte_Ptr aStart, Dwarf_Byte_Ptr aEnd){ + Dwarf_Byte_Ptr start = aStart; + Dwarf_Byte_Ptr end = aEnd; + size_t bytes_read = 0; + while (start < end){ + Dwarf_Byte_Ptr hdrptr = start; + size_t offset_size, initial_length_size; + + Dwarf_Word length = READ_UNALIGNED4(hdrptr); + hdrptr += 4; + + if (length >= 0xfffffff0u) { + cerr << "Error: 64 bit DWARF not supported\n"; + exit(EXIT_FAILURE); + } else { + offset_size = 4; + initial_length_size = 4; + } + + Dwarf_Byte_Ptr end_of_sequence = start + length + initial_length_size; + + Dwarf_Half version = READ_UNALIGNED2(hdrptr); + hdrptr += 2; + + if (version != 2 && version != 3){ + static bool warned = false; + if (!warned){ + cerr << "Only DWARF 2 and 3 aranges are currently supported\n"; + warned = true; + } + return; + } + + hdrptr += offset_size; +#if 0 + // Don't need the next four fields + Dwarf_Ubyte min_insn_length = *hdrptr++; + Dwarf_Ubyte default_is_stmt = *hdrptr++; + Dwarf_Ubyte line_base = *hdrptr++; + Dwarf_Ubyte line_range = *hdrptr++; +#endif + hdrptr +=4; + Dwarf_Ubyte opcode_base = *hdrptr++; + + /* Skip the contents of the Opcodes table. */ + Dwarf_Byte_Ptr standard_opcodes = hdrptr; + start = standard_opcodes + opcode_base - 1; + + /* skip the contents of the Directory table. */ + while (*start != 0){ + start += strlen ((char *) start) + 1; + } + /* Skip the NUL at the end of the table. */ + start++; + + /* skip the contents of the File Name table. */ + while (*start != 0){ + start += strlen ((char *) start) + 1; + + ULEB128(start, bytes_read); + ULEB128(start, bytes_read); + ULEB128(start, bytes_read); + } + /* Skip the NUL at the end of the table. */ + start++; + + while (start < end_of_sequence){ + unsigned char op_code = *start++; + + if (op_code >= opcode_base){ + continue; + } else { + switch (op_code){ +// missing from dwarf.h - first byte of extended op codes is '0x0' +#define DW_LNS_extended_op 0x0 + case DW_LNS_extended_op: + size_t n = process_extended_line_op (aPair, start); + // if we don't understand the extended op skip to the end of the sequence :-( + if (n == 0) + start = end_of_sequence; + else + start += n; + break; + + case DW_LNS_copy: + break; + + case DW_LNS_advance_pc: + case DW_LNS_advance_line: + case DW_LNS_set_file: + case DW_LNS_set_column: + ULEB128(start, bytes_read); + break; + + case DW_LNS_negate_stmt: + case DW_LNS_set_basic_block: + case DW_LNS_const_add_pc: + break; + + case DW_LNS_fixed_advance_pc: + start += 2; + break; + + case DW_LNS_set_prologue_end: + case DW_LNS_set_epilogue_begin: + break; + + case DW_LNS_set_isa: + ULEB128(start, bytes_read); + break; + + default: + for (int i = standard_opcodes[op_code - 1]; i > 0 ; --i){ + ULEB128(start, bytes_read); + } + break; + } + } + } + // !! eek ARM seems to require header word aligned - at least for Dwarf 2 + if (aPair.iXIPFileDetails.iRVCTProduced && (version == 2)) + start = (Dwarf_Byte_Ptr)(((unsigned long)start + 3) & ~3); + } +}