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