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