summaryrefslogtreecommitdiff
path: root/usr/src/tools/ctf/dwarf/common/dwarf_line.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/tools/ctf/dwarf/common/dwarf_line.c')
-rw-r--r--usr/src/tools/ctf/dwarf/common/dwarf_line.c2637
1 files changed, 1520 insertions, 1117 deletions
diff --git a/usr/src/tools/ctf/dwarf/common/dwarf_line.c b/usr/src/tools/ctf/dwarf/common/dwarf_line.c
index 6e5556ef85..e7e15e7c1a 100644
--- a/usr/src/tools/ctf/dwarf/common/dwarf_line.c
+++ b/usr/src/tools/ctf/dwarf/common/dwarf_line.c
@@ -1,6 +1,6 @@
/*
-
- Copyright (C) 2000,2002,2004 Silicon Graphics, Inc. All Rights Reserved.
+ Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007-2010 David Anderson. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of version 2.1 of the GNU Lesser General Public License
@@ -19,10 +19,10 @@
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
USA.
- Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky,
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
Mountain View, CA 94043, or:
http://www.sgi.com
@@ -32,17 +32,62 @@
http://oss.sgi.com/projects/GenInfo/NoticeExplan
*/
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
#include "config.h"
#include "dwarf_incl.h"
#include <stdio.h>
+#include <stdlib.h>
#include "dwarf_line.h"
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
+
+static int
+is_path_separator(Dwarf_Small s)
+{
+ if(s == '/') {
+ return 1;
+ }
+#ifdef HAVE_WINDOWS_PATH
+ if(s == '\\') {
+ return 1;
+ }
#endif
+ return 0;
+}
+/* Return 0 if false, 1 if true.
+ If HAVE_WINDOWS_PATH is defined we
+ attempt to handle windows full paths:
+ \\something or C:cwdpath.c
+*/
+static int
+file_name_is_full_path(Dwarf_Small *fname)
+{
+ Dwarf_Small firstc = *fname;
+ if(is_path_separator(firstc)) {
+ /* Full path. */
+ return 1;
+ }
+ if(!firstc) {
+ return 0;
+ }
+#ifdef HAVE_WINDOWS_PATH
+ if((firstc >= 'A' && firstc <= 'Z') ||
+ (firstc >= 'a' && firstc <= 'z')) {
+ Dwarf_Small secondc = fname[1];
+ if (secondc == ':') {
+ return 1;
+ }
+ }
+#endif
+ return 0;
+}
/*
Although source files is supposed to return the
@@ -53,27 +98,14 @@
*/
int
dwarf_srcfiles(Dwarf_Die die,
- char ***srcfiles,
- Dwarf_Signed * srcfilecount, Dwarf_Error * error)
+ char ***srcfiles,
+ Dwarf_Signed * srcfilecount, Dwarf_Error * error)
{
- /*
- This pointer is used to scan the portion of the .debug_line
+ /* This pointer is used to scan the portion of the .debug_line
section for the current cu. */
Dwarf_Small *line_ptr;
- /*
- This points to the last byte of the .debug_line portion for the
- current cu. */
- Dwarf_Small *line_ptr_end;
-
- /*
- This points to the end of the statement program prologue for the
- current cu, and serves to check that the prologue was correctly
- decoded. */
- Dwarf_Small *check_line_ptr;
-
- /*
- Pointer to a DW_AT_stmt_list attribute in case it exists in the
+ /* Pointer to a DW_AT_stmt_list attribute in case it exists in the
die. */
Dwarf_Attribute stmt_list_attr;
@@ -83,100 +115,69 @@ dwarf_srcfiles(Dwarf_Die die,
/* Pointer to name of compilation directory. */
Dwarf_Small *comp_dir = 0;
- /*
- Offset into .debug_line specified by a DW_AT_stmt_list
+ /* Offset into .debug_line specified by a DW_AT_stmt_list
attribute. */
Dwarf_Unsigned line_offset = 0;
- /* Some of the fields of the statement program header. */
- Dwarf_Unsigned total_length = 0;
- Dwarf_Half version = 0;
- Dwarf_Unsigned prologue_length = 0;
- Dwarf_Small special_opcode_base= 0;
-
- /* File name excluding included directory. */
- char *file_name = 0;
-
- /* Name of directory that the file is in. */
- char *dir_name = 0;
-
- /* Name concatenating both directory and file name. */
- char *full_name = 0;
-
- /*
- This is the directory index for the file. The compilation
- directory is 0, and the first included directory is 1. */
- Dwarf_Sword dir_index = 0;
-
- Dwarf_Small *include_directories = 0;
-
- Dwarf_Sword i = 0;
- Dwarf_Sword file_count = 0;
- Dwarf_Sword directories_count = 0;
-
- /*
- This is the current opcode read from the statement program. */
-
- Dwarf_Word leb128_length;
-
- /* This is the length of an extended opcode instr. */
-
- /*
- This points to a block of char *'s, each of which points to a
+ /* This points to a block of char *'s, each of which points to a
file name. */
char **ret_files = 0;
/* The Dwarf_Debug this die belongs to. */
- Dwarf_Debug dbg;
+ Dwarf_Debug dbg = 0;
/* Used to chain the file names. */
- Dwarf_Chain curr_chain, prev_chain, head_chain = NULL;
- int resattr;
- int lres;
-
- int local_length_size = 0;
- /*REFERENCED*/ /* Not used in this instance of the macro */
- int local_extension_size = 0;
-
- int res;
+ Dwarf_Chain curr_chain = NULL;
+ Dwarf_Chain prev_chain = NULL;
+ Dwarf_Chain head_chain = NULL;
+ Dwarf_Half attrform = 0;
+ int resattr = DW_DLV_ERROR;
+ int lres = DW_DLV_ERROR;
+ struct Line_Table_Prefix_s line_prefix;
+ int i = 0;
+ int res = DW_DLV_ERROR;
/* ***** BEGIN CODE ***** */
-
/* Reset error. */
if (error != NULL)
- *error = NULL;
+ *error = NULL;
- CHECK_DIE(die, DW_DLV_ERROR)
- dbg = die->di_cu_context->cc_dbg;
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
if (resattr != DW_DLV_OK) {
- return resattr;
+ return resattr;
}
-
- if (dbg->de_debug_line_index == 0) {
- _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_NULL);
- return (DW_DLV_ERROR);
+
+ if (dbg->de_debug_line.dss_index == 0) {
+ _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_NULL);
+ return (DW_DLV_ERROR);
}
- res =
- _dwarf_load_section(dbg,
- dbg->de_debug_line_index,
- &dbg->de_debug_line,
- error);
+ res = _dwarf_load_section(dbg, &dbg->de_debug_line,error);
if (res != DW_DLV_OK) {
- return res;
+ return res;
}
- lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
+ lres = dwarf_whatform(stmt_list_attr,&attrform,error);
+ if (lres != DW_DLV_OK) {
+ return lres;
+ }
+ if (attrform != DW_FORM_data4 && attrform != DW_FORM_data8 &&
+ attrform != DW_FORM_sec_offset ) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
+ }
+ lres = dwarf_global_formref(stmt_list_attr, &line_offset, error);
if (lres != DW_DLV_OK) {
- return lres;
+ return lres;
}
- if (line_offset >= dbg->de_debug_line_size) {
- _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
- return (DW_DLV_ERROR);
+ if (line_offset >= dbg->de_debug_line.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
}
- line_ptr = dbg->de_debug_line + line_offset;
+ line_ptr = dbg->de_debug_line.dss_data + line_offset;
dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
/*
@@ -184,920 +185,849 @@ dwarf_srcfiles(Dwarf_Die die,
the compilation directory. */
resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
if (resattr == DW_DLV_ERROR) {
- return resattr;
+ return resattr;
}
if (resattr == DW_DLV_OK) {
- int cres;
- char *cdir;
-
- cres = dwarf_formstring(comp_dir_attr, &cdir, error);
- if (cres == DW_DLV_ERROR) {
- return cres;
- } else if (cres == DW_DLV_OK) {
- comp_dir = (Dwarf_Small *) cdir;
- }
+ int cres = DW_DLV_ERROR;
+ char *cdir = 0;
+
+ cres = dwarf_formstring(comp_dir_attr, &cdir, error);
+ if (cres == DW_DLV_ERROR) {
+ return cres;
+ } else if (cres == DW_DLV_OK) {
+ comp_dir = (Dwarf_Small *) cdir;
+ }
}
if (resattr == DW_DLV_OK) {
- dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
+ dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
}
-
- /*
- Following is a straightforward decoding of the statement
- program prologue information. */
- /* READ_AREA_LENGTH updates line_ptr for consumed bytes */
- READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned,
- line_ptr, local_length_size, local_extension_size);
-
-
- line_ptr_end = line_ptr + total_length;
- if (line_ptr_end > dbg->de_debug_line + dbg->de_debug_line_size) {
- _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
- return (DW_DLV_ERROR);
+ dwarf_init_line_table_prefix(&line_prefix);
+ {
+ Dwarf_Small *line_ptr_out = 0;
+ int dres = dwarf_read_line_table_prefix(dbg,
+ line_ptr,
+ dbg->de_debug_line.dss_size,
+ &line_ptr_out,
+ &line_prefix,
+ NULL, NULL,error,
+ 0);
+
+ if (dres == DW_DLV_ERROR) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ return dres;
+ }
+ if (dres == DW_DLV_NO_ENTRY) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ return dres;
+ }
+
+ line_ptr = line_ptr_out;
}
- READ_UNALIGNED(dbg, version, Dwarf_Half,
- line_ptr, sizeof(Dwarf_Half));
- line_ptr += sizeof(Dwarf_Half);
- if (version != CURRENT_VERSION_STAMP) {
- _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
- return (DW_DLV_ERROR);
+ for (i = 0; i < line_prefix.pf_files_count; ++i) {
+ struct Line_Table_File_Entry_s *fe =
+ line_prefix.pf_line_table_file_entries + i;
+ char *file_name = (char *) fe->lte_filename;
+ char *dir_name = 0;
+ char *full_name = 0;
+ Dwarf_Unsigned dir_index = fe->lte_directory_index;
+
+ if (dir_index == 0) {
+ dir_name = (char *) comp_dir;
+ } else {
+ dir_name =
+ (char *) line_prefix.pf_include_directories[
+ fe->lte_directory_index - 1];
+ }
+
+ /* dir_name can be NULL if there is no DW_AT_comp_dir */
+ if(dir_name == 0 || file_name_is_full_path((unsigned char *)file_name)) {
+ /* This is safe because dwarf_dealloc is careful to not
+ dealloc strings which are part of the raw .debug_* data.
+ */
+ full_name = file_name;
+ } else {
+ full_name = (char *) _dwarf_get_alloc(dbg, DW_DLA_STRING,
+ strlen(dir_name) + 1 +
+ strlen(file_name) +
+ 1);
+ if (full_name == NULL) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ /* This is not careful to avoid // in the output, Nothing
+ forces a 'canonical' name format here. Unclear if this
+ needs to be fixed. */
+ strcpy(full_name, dir_name);
+ strcat(full_name, "/");
+ strcat(full_name, file_name);
+ }
+ curr_chain =
+ (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ curr_chain->ch_item = full_name;
+ if (head_chain == NULL)
+ head_chain = prev_chain = curr_chain;
+ else {
+ prev_chain->ch_next = curr_chain;
+ prev_chain = curr_chain;
+ }
}
- READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
- line_ptr, local_length_size);
- line_ptr += local_length_size;
- check_line_ptr = line_ptr;
-
- /* Skip over minimum instruction length. */
- line_ptr = line_ptr + sizeof(Dwarf_Small);
-
- /* Skip over default_is_stmt. */
- line_ptr = line_ptr + sizeof(Dwarf_Small);
-
- /* Skip over line_base. */
- line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
-
- /* Skip over line_ptr. */
- line_ptr = line_ptr + sizeof(Dwarf_Small);
-
- special_opcode_base = *(Dwarf_Small *) line_ptr;
- line_ptr = line_ptr + sizeof(Dwarf_Small);
-
- for (i = 1; i < special_opcode_base; i++) {
- /* Skip over opcode lengths for standard opcodes. */
- line_ptr = line_ptr + sizeof(Dwarf_Small);
+ curr_chain = (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (curr_chain == NULL) {
+ dwarf_free_line_table_prefix(&line_prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
}
- directories_count = 0;
- include_directories = line_ptr;
- while ((*(char *) line_ptr) != '\0') {
- line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
- directories_count++;
- }
- line_ptr++;
- file_count = 0;
- while (*(char *) line_ptr != '\0') {
- Dwarf_Unsigned utmp;
-
- file_name = (char *) line_ptr;
- line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
-
- DECODE_LEB128_UWORD(line_ptr, utmp)
- dir_index = (Dwarf_Sword) utmp;
- if (dir_index > directories_count) {
- _dwarf_error(dbg, error, DW_DLE_DIR_INDEX_BAD);
- return (DW_DLV_ERROR);
- }
-
- if (dir_index == 0)
- dir_name = (char *) comp_dir;
- else {
- dir_name = (char *) include_directories;
- for (i = 1; i < dir_index; i++)
- /* FIX: this is probably very slow: redoing strlen!
- davea 9/94 */
- dir_name = dir_name + strlen(dir_name) + 1;
- }
-
- /* dir_name can be NULL if there is no DW_AT_comp_dir */
- if ((*file_name) == '/' || dir_name == 0)
- full_name = file_name;
- else {
- full_name = (char *) _dwarf_get_alloc(dbg, DW_DLA_STRING,
- strlen(dir_name) + 1 +
- strlen(file_name) +
- 1);
- if (full_name == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- strcpy(full_name, dir_name);
- strcat(full_name, "/");
- strcat(full_name, file_name);
- }
-
- /* Skip over time of last modification. */
- _dwarf_decode_u_leb128(line_ptr, &leb128_length);
- line_ptr = line_ptr + leb128_length;
-
- /* Skip over file length. */
- _dwarf_decode_u_leb128(line_ptr, &leb128_length);
- line_ptr = line_ptr + leb128_length;
-
- curr_chain =
- (Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (curr_chain == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- curr_chain->ch_item = full_name;
-
- if (head_chain == NULL)
- head_chain = prev_chain = curr_chain;
- else {
- prev_chain->ch_next = curr_chain;
- prev_chain = curr_chain;
- }
-
- file_count++;
- }
- line_ptr++;
- if (line_ptr != check_line_ptr + prologue_length) {
- _dwarf_error(dbg, error, DW_DLE_LINE_PROLOG_LENGTH_BAD);
- return (DW_DLV_ERROR);
- }
- if (file_count == 0) {
- *srcfiles = NULL;
- *srcfilecount = 0;
- return (DW_DLV_NO_ENTRY);
+ if (line_prefix.pf_files_count == 0) {
+ *srcfiles = NULL;
+ *srcfilecount = 0;
+ dwarf_free_line_table_prefix(&line_prefix);
+ return (DW_DLV_NO_ENTRY);
}
ret_files = (char **)
- _dwarf_get_alloc(dbg, DW_DLA_LIST, file_count);
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, line_prefix.pf_files_count);
if (ret_files == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ dwarf_free_line_table_prefix(&line_prefix);
+ return (DW_DLV_ERROR);
}
curr_chain = head_chain;
- for (i = 0; i < file_count; i++) {
- *(ret_files + i) = curr_chain->ch_item;
- prev_chain = curr_chain;
- curr_chain = curr_chain->ch_next;
- dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
+ for (i = 0; i < line_prefix.pf_files_count; i++) {
+ *(ret_files + i) = curr_chain->ch_item;
+ prev_chain = curr_chain;
+ curr_chain = curr_chain->ch_next;
+ dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
}
*srcfiles = ret_files;
- *srcfilecount = file_count;
+ *srcfilecount = line_prefix.pf_files_count;
+ dwarf_free_line_table_prefix(&line_prefix);
return (DW_DLV_OK);
}
/*
- return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
+ return DW_DLV_OK if ok. else DW_DLV_NO_ENTRY or DW_DLV_ERROR
*/
int
_dwarf_internal_srclines(Dwarf_Die die,
- Dwarf_Line ** linebuf,
- Dwarf_Signed * count,
- Dwarf_Bool doaddrs,
- Dwarf_Bool dolines, Dwarf_Error * error)
+ Dwarf_Line ** linebuf,
+ Dwarf_Signed * count,
+ Dwarf_Bool doaddrs,
+ Dwarf_Bool dolines, Dwarf_Error * error)
{
- /*
- This pointer is used to scan the portion of the .debug_line
+ /* This pointer is used to scan the portion of the .debug_line
section for the current cu. */
- Dwarf_Small *line_ptr;
+ Dwarf_Small *line_ptr = 0;
- /*
- This points to the last byte of the .debug_line portion for the
+ /* This points to the last byte of the .debug_line portion for the
current cu. */
- Dwarf_Small *line_ptr_end;
-
- /*
- This points to the end of the statement program prologue for the
- current cu, and serves to check that the prologue was correctly
- decoded. */
- Dwarf_Small *check_line_ptr;
+ Dwarf_Small *line_ptr_end = 0;
- /*
- Pointer to a DW_AT_stmt_list attribute in case it exists in the
+ /* Pointer to a DW_AT_stmt_list attribute in case it exists in the
die. */
- Dwarf_Attribute stmt_list_attr;
+ Dwarf_Attribute stmt_list_attr = 0;
/* Pointer to DW_AT_comp_dir attribute in die. */
- Dwarf_Attribute comp_dir_attr;
+ Dwarf_Attribute comp_dir_attr = 0;
/* Pointer to name of compilation directory. */
Dwarf_Small *comp_dir = NULL;
- /*
- Offset into .debug_line specified by a DW_AT_stmt_list
+ /* Offset into .debug_line specified by a DW_AT_stmt_list
attribute. */
- Dwarf_Unsigned line_offset;
-
- /* These are the fields of the statement program header. */
- Dwarf_Unsigned total_length;
- Dwarf_Half version;
- Dwarf_Unsigned prologue_length;
- Dwarf_Small minimum_instruction_length;
- Dwarf_Small default_is_stmt;
- Dwarf_Sbyte line_base;
- Dwarf_Small line_range;
- Dwarf_Small special_opcode_base;
-
- Dwarf_Small *opcode_length;
- Dwarf_Small *include_directories;
- Dwarf_File_Entry file_entries;
+ Dwarf_Unsigned line_offset = 0;
- /* These are the state machine state variables. */
- Dwarf_Addr address;
- Dwarf_Word file;
- Dwarf_Word line;
- Dwarf_Word column;
- Dwarf_Bool is_stmt;
- Dwarf_Bool basic_block;
- Dwarf_Bool end_sequence;
+ Dwarf_File_Entry file_entries = 0;
- /*
- These pointers are used to build the list of files names by
- this cu. cur_file_entry points to the file name being added,
- and prev_file_entry to the previous one. */
+ /* These are the state machine state variables. */
+ Dwarf_Addr address = 0;
+ Dwarf_Word file = 1;
+ Dwarf_Word line = 1;
+ Dwarf_Word column = 0;
+
+ /* Phony init. See below for true initialization. */
+ Dwarf_Bool is_stmt = false;
+
+ Dwarf_Bool basic_block = false;
+ Dwarf_Bool prologue_end = false;
+ Dwarf_Bool epilogue_begin = false;
+ Dwarf_Small isa = 0;
+ Dwarf_Bool end_sequence = false;
+
+ /* These pointers are used to build the list of files names by this
+ cu. cur_file_entry points to the file name being added, and
+ prev_file_entry to the previous one. */
Dwarf_File_Entry cur_file_entry, prev_file_entry;
- Dwarf_Sword i, file_entry_count, include_directories_count;
+ Dwarf_Sword i = 0;
+ Dwarf_Sword file_entry_count = 0;
- /*
- This is the current opcode read from the statement program. */
- Dwarf_Small opcode;
+ /* This is the current opcode read from the statement program. */
+ Dwarf_Small opcode = 0;
- /*
- Pointer to a Dwarf_Line_Context_s structure that contains the
+ /* Pointer to a Dwarf_Line_Context_s structure that contains the
context such as file names and include directories for the set
of lines being generated. */
- Dwarf_Line_Context line_context;
+ Dwarf_Line_Context line_context = 0;
- /*
- This is a pointer to the current line being added to the line
+ /* This is a pointer to the current line being added to the line
matrix. */
- Dwarf_Line curr_line;
+ Dwarf_Line curr_line = 0;
- /*
- These variables are used to decode leb128 numbers. Leb128_num
+ /* These variables are used to decode leb128 numbers. Leb128_num
holds the decoded number, and leb128_length is its length in
bytes. */
- Dwarf_Word leb128_num;
- Dwarf_Word leb128_length;
- Dwarf_Sword advance_line;
+ Dwarf_Word leb128_num = 0;
+ Dwarf_Word leb128_length = 0;
+ Dwarf_Sword advance_line = 0;
- /*
- This is the operand of the latest fixed_advance_pc extended
+ /* This is the operand of the latest fixed_advance_pc extended
opcode. */
- Dwarf_Half fixed_advance_pc;
+ Dwarf_Half fixed_advance_pc = 0;
- /*
- Counts the number of lines in the line matrix. */
+ /* Counts the number of lines in the line matrix. */
Dwarf_Sword line_count = 0;
/* This is the length of an extended opcode instr. */
- Dwarf_Word instr_length;
- Dwarf_Small ext_opcode;
+ Dwarf_Word instr_length = 0;
+ Dwarf_Small ext_opcode = 0;
+ struct Line_Table_Prefix_s prefix;
- /*
- Used to chain together pointers to line table entries that are
+ /* Used to chain together pointers to line table entries that are
later used to create a block of Dwarf_Line entries. */
- Dwarf_Chain chain_line, head_chain = NULL, curr_chain;
+ Dwarf_Chain chain_line = NULL;
+ Dwarf_Chain head_chain = NULL;
+ Dwarf_Chain curr_chain = NULL;
- /*
- This points to a block of Dwarf_Lines, a pointer to which is
+ /* This points to a block of Dwarf_Lines, a pointer to which is
returned in linebuf. */
- Dwarf_Line *block_line;
+ Dwarf_Line *block_line = 0;
/* The Dwarf_Debug this die belongs to. */
- Dwarf_Debug dbg;
- int resattr;
- int lres;
- int local_length_size = 0;
- /*REFERENCED*/ /* Not used in this instance of the macro */
- int local_extension_size = 0;
+ Dwarf_Debug dbg = 0;
+ int resattr = DW_DLV_ERROR;
+ int lres = DW_DLV_ERROR;
+ Dwarf_Half address_size = 0;
- int res;
+ int res = DW_DLV_ERROR;
/* ***** BEGIN CODE ***** */
-
if (error != NULL)
- *error = NULL;
+ *error = NULL;
- CHECK_DIE(die, DW_DLV_ERROR)
- dbg = die->di_cu_context->cc_dbg;
+ CHECK_DIE(die, DW_DLV_ERROR);
+ dbg = die->di_cu_context->cc_dbg;
- res =
- _dwarf_load_section(dbg,
- dbg->de_debug_line_index,
- &dbg->de_debug_line,
- error);
+ res = _dwarf_load_section(dbg, &dbg->de_debug_line,error);
if (res != DW_DLV_OK) {
- return res;
+ return res;
}
-
+ address_size = _dwarf_get_address_size(dbg, die);
resattr = dwarf_attr(die, DW_AT_stmt_list, &stmt_list_attr, error);
if (resattr != DW_DLV_OK) {
- return resattr;
+ return resattr;
}
-
-
lres = dwarf_formudata(stmt_list_attr, &line_offset, error);
if (lres != DW_DLV_OK) {
- return lres;
+ return lres;
}
- if (line_offset >= dbg->de_debug_line_size) {
- _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
- return (DW_DLV_ERROR);
+ if (line_offset >= dbg->de_debug_line.dss_size) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_OFFSET_BAD);
+ return (DW_DLV_ERROR);
}
- line_ptr = dbg->de_debug_line + line_offset;
+ line_ptr = dbg->de_debug_line.dss_data + line_offset;
dwarf_dealloc(dbg, stmt_list_attr, DW_DLA_ATTR);
- /*
- If die has DW_AT_comp_dir attribute, get the string that names
+ /* If die has DW_AT_comp_dir attribute, get the string that names
the compilation directory. */
resattr = dwarf_attr(die, DW_AT_comp_dir, &comp_dir_attr, error);
if (resattr == DW_DLV_ERROR) {
- return resattr;
+ return resattr;
}
if (resattr == DW_DLV_OK) {
- int cres;
- char *cdir;
-
- cres = dwarf_formstring(comp_dir_attr, &cdir, error);
- if (cres == DW_DLV_ERROR) {
- return cres;
- } else if (cres == DW_DLV_OK) {
- comp_dir = (Dwarf_Small *) cdir;
- }
+ int cres = DW_DLV_ERROR;
+ char *cdir = 0;
+
+ cres = dwarf_formstring(comp_dir_attr, &cdir, error);
+ if (cres == DW_DLV_ERROR) {
+ return cres;
+ } else if (cres == DW_DLV_OK) {
+ comp_dir = (Dwarf_Small *) cdir;
+ }
}
if (resattr == DW_DLV_OK) {
- dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
- }
-
- /*
- Following is a straightforward decoding of the statement
- program prologue information. */
- /* READ_AREA_LENGTH updates line_ptr for consumed bytes */
- READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned,
- line_ptr, local_length_size, local_extension_size);
-
- line_ptr_end = line_ptr + total_length;
- if (line_ptr_end > dbg->de_debug_line + dbg->de_debug_line_size) {
- _dwarf_error(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD);
- return (DW_DLV_ERROR);
+ dwarf_dealloc(dbg, comp_dir_attr, DW_DLA_ATTR);
}
-
- READ_UNALIGNED(dbg, version, Dwarf_Half,
- line_ptr, sizeof(Dwarf_Half));
- line_ptr += sizeof(Dwarf_Half);
- if (version != CURRENT_VERSION_STAMP) {
- _dwarf_error(dbg, error, DW_DLE_VERSION_STAMP_ERROR);
- return (DW_DLV_ERROR);
+ dwarf_init_line_table_prefix(&prefix);
+
+ {
+ Dwarf_Small *newlinep = 0;
+ int res = dwarf_read_line_table_prefix(dbg,
+ line_ptr,
+ dbg->de_debug_line.dss_size,
+ &newlinep,
+ &prefix,
+ NULL,NULL,
+ error,
+ 0);
+
+ if (res == DW_DLV_ERROR) {
+ dwarf_free_line_table_prefix(&prefix);
+ return res;
+ }
+ if (res == DW_DLV_NO_ENTRY) {
+ dwarf_free_line_table_prefix(&prefix);
+ return res;
+ }
+ line_ptr_end = prefix.pf_line_ptr_end;
+ line_ptr = newlinep;
}
- READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
- line_ptr, local_length_size);
- line_ptr += local_length_size;
- check_line_ptr = line_ptr;
-
- minimum_instruction_length = *(Dwarf_Small *) line_ptr;
- line_ptr = line_ptr + sizeof(Dwarf_Small);
-
- default_is_stmt = *(Dwarf_Small *) line_ptr;
- line_ptr = line_ptr + sizeof(Dwarf_Small);
-
- line_base = *(Dwarf_Sbyte *) line_ptr;
- line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
- line_range = *(Dwarf_Small *) line_ptr;
- line_ptr = line_ptr + sizeof(Dwarf_Small);
-
- special_opcode_base = *(Dwarf_Small *) line_ptr;
- line_ptr = line_ptr + sizeof(Dwarf_Small);
-
- opcode_length = (Dwarf_Small *)
- alloca(sizeof(Dwarf_Small) * special_opcode_base);
- for (i = 1; i < special_opcode_base; i++) {
- opcode_length[i] = *(Dwarf_Small *) line_ptr;
- line_ptr = line_ptr + sizeof(Dwarf_Small);
+ /* Set up context structure for this set of lines. */
+ line_context = (Dwarf_Line_Context)
+ _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1);
+ if (line_context == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
}
- include_directories_count = 0;
- include_directories = line_ptr;
- while ((*(char *) line_ptr) != '\0') {
- line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
- include_directories_count++;
- }
- line_ptr++;
-
- file_entry_count = 0;
+ /* Fill out a Dwarf_File_Entry list as we use that to implement the
+ define_file operation. */
file_entries = prev_file_entry = NULL;
- while (*(char *) line_ptr != '\0') {
-
- cur_file_entry = (Dwarf_File_Entry)
- _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
- if (cur_file_entry == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- cur_file_entry->fi_file_name = (Dwarf_Small *) line_ptr;
- line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
-
- cur_file_entry->fi_dir_index =
- (Dwarf_Sword) _dwarf_decode_u_leb128(line_ptr,
- &leb128_length);
- line_ptr = line_ptr + leb128_length;
-
- cur_file_entry->fi_time_last_mod =
- _dwarf_decode_u_leb128(line_ptr, &leb128_length);
- line_ptr = line_ptr + leb128_length;
-
- cur_file_entry->fi_file_length =
- _dwarf_decode_u_leb128(line_ptr, &leb128_length);
- line_ptr = line_ptr + leb128_length;
-
- if (file_entries == NULL)
- file_entries = cur_file_entry;
- else
- prev_file_entry->fi_next = cur_file_entry;
- prev_file_entry = cur_file_entry;
-
- file_entry_count++;
+ for (i = 0; i < prefix.pf_files_count; ++i) {
+ struct Line_Table_File_Entry_s *pfxfile =
+ prefix.pf_line_table_file_entries + i;
+
+ cur_file_entry = (Dwarf_File_Entry)
+ _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
+ if (cur_file_entry == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ cur_file_entry->fi_file_name = pfxfile->lte_filename;
+ cur_file_entry->fi_dir_index = pfxfile->lte_directory_index;
+ cur_file_entry->fi_time_last_mod =
+ pfxfile->lte_last_modification_time;
+
+ cur_file_entry->fi_file_length = pfxfile->lte_length_of_file;
+
+ if (file_entries == NULL)
+ file_entries = cur_file_entry;
+ else
+ prev_file_entry->fi_next = cur_file_entry;
+ prev_file_entry = cur_file_entry;
+
+ file_entry_count++;
}
- line_ptr++;
- if (line_ptr != check_line_ptr + prologue_length) {
- _dwarf_error(dbg, error, DW_DLE_LINE_PROLOG_LENGTH_BAD);
- return (DW_DLV_ERROR);
- }
- /* Set up context structure for this set of lines. */
- line_context = (Dwarf_Line_Context)
- _dwarf_get_alloc(dbg, DW_DLA_LINE_CONTEXT, 1);
- if (line_context == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
+ /* Initialize the one state machine variable that depends on the
+ prefix. */
+ is_stmt = prefix.pf_default_is_stmt;
- /* Initialize the state machine. */
- address = 0;
- file = 1;
- line = 1;
- column = 0;
- is_stmt = default_is_stmt;
- basic_block = false;
- end_sequence = false;
/* Start of statement program. */
while (line_ptr < line_ptr_end) {
- int type;
-
- opcode = *(Dwarf_Small *) line_ptr;
- line_ptr++;
-
-
- /* 'type' is the output */
- WHAT_IS_OPCODE(type, opcode, special_opcode_base,
- opcode_length, line_ptr);
-
-
-
- if (type == LOP_DISCARD) {
- /* do nothing, necessary ops done */
- } else if (type == LOP_SPECIAL) {
- /* This op code is a special op in the object, no matter
- that it might fall into the standard op range in this
- compile Thatis, these are special opcodes between
- special_opcode_base and MAX_LINE_OP_CODE. (including
- special_opcode_base and MAX_LINE_OP_CODE) */
-
- opcode = opcode - special_opcode_base;
- address = address + minimum_instruction_length *
- (opcode / line_range);
- line = line + line_base + opcode % line_range;
-
- if (dolines) {
- curr_line =
- (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
- if (curr_line == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- curr_line->li_address = address;
- curr_line->li_addr_line.li_l_data.li_file =
- (Dwarf_Sword) file;
- curr_line->li_addr_line.li_l_data.li_line =
- (Dwarf_Sword) line;
- curr_line->li_addr_line.li_l_data.li_column =
- (Dwarf_Half) column;
- curr_line->li_addr_line.li_l_data.li_is_stmt = is_stmt;
- curr_line->li_addr_line.li_l_data.li_basic_block =
- basic_block;
- curr_line->li_addr_line.li_l_data.li_end_sequence =
- end_sequence;
- curr_line->li_context = line_context;
- line_count++;
-
- chain_line = (Dwarf_Chain)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (chain_line == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
- chain_line->ch_item = curr_line;
-
- if (head_chain == NULL)
- head_chain = curr_chain = chain_line;
- else {
- curr_chain->ch_next = chain_line;
- curr_chain = chain_line;
- }
- }
-
- basic_block = false;
- } else if (type == LOP_STANDARD) {
- switch (opcode) {
-
- case DW_LNS_copy:{
- if (opcode_length[DW_LNS_copy] != 0) {
- _dwarf_error(dbg, error,
- DW_DLE_LINE_NUM_OPERANDS_BAD);
- return (DW_DLV_ERROR);
- }
-
- if (dolines) {
-
- curr_line =
- (Dwarf_Line) _dwarf_get_alloc(dbg,
- DW_DLA_LINE,
- 1);
- if (curr_line == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- curr_line->li_address = address;
- curr_line->li_addr_line.li_l_data.li_file =
- (Dwarf_Sword) file;
- curr_line->li_addr_line.li_l_data.li_line =
- (Dwarf_Sword) line;
- curr_line->li_addr_line.li_l_data.li_column =
- (Dwarf_Half) column;
- curr_line->li_addr_line.li_l_data.li_is_stmt =
- is_stmt;
- curr_line->li_addr_line.li_l_data.
- li_basic_block = basic_block;
- curr_line->li_addr_line.li_l_data.
- li_end_sequence = end_sequence;
- curr_line->li_context = line_context;
- line_count++;
-
- chain_line = (Dwarf_Chain)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (chain_line == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
- chain_line->ch_item = curr_line;
- if (head_chain == NULL)
- head_chain = curr_chain = chain_line;
- else {
- curr_chain->ch_next = chain_line;
- curr_chain = chain_line;
- }
- }
-
- basic_block = false;
- break;
- }
-
- case DW_LNS_advance_pc:{
- Dwarf_Unsigned utmp2;
-
- if (opcode_length[DW_LNS_advance_pc] != 1) {
- _dwarf_error(dbg, error,
- DW_DLE_LINE_NUM_OPERANDS_BAD);
- return (DW_DLV_ERROR);
- }
-
- DECODE_LEB128_UWORD(line_ptr, utmp2)
- leb128_num = (Dwarf_Word) utmp2;
- address =
- address +
- minimum_instruction_length * leb128_num;
- break;
- }
-
- case DW_LNS_advance_line:{
- Dwarf_Signed stmp;
-
- if (opcode_length[DW_LNS_advance_line] != 1) {
- _dwarf_error(dbg, error,
- DW_DLE_LINE_NUM_OPERANDS_BAD);
- return (DW_DLV_ERROR);
- }
-
- DECODE_LEB128_SWORD(line_ptr, stmp)
- advance_line = (Dwarf_Sword) stmp;
- line = line + advance_line;
- break;
- }
-
- case DW_LNS_set_file:{
- Dwarf_Unsigned utmp2;
-
- if (opcode_length[DW_LNS_set_file] != 1) {
- _dwarf_error(dbg, error,
- DW_DLE_LINE_NUM_OPERANDS_BAD);
- return (DW_DLV_ERROR);
- }
-
- DECODE_LEB128_UWORD(line_ptr, utmp2)
- file = (Dwarf_Word) utmp2;
- break;
- }
-
- case DW_LNS_set_column:{
- Dwarf_Unsigned utmp2;
-
- if (opcode_length[DW_LNS_set_column] != 1) {
- _dwarf_error(dbg, error,
- DW_DLE_LINE_NUM_OPERANDS_BAD);
- return (DW_DLV_ERROR);
- }
-
- DECODE_LEB128_UWORD(line_ptr, utmp2)
- column = (Dwarf_Word) utmp2;
- break;
- }
-
- case DW_LNS_negate_stmt:{
- if (opcode_length[DW_LNS_negate_stmt] != 0) {
- _dwarf_error(dbg, error,
- DW_DLE_LINE_NUM_OPERANDS_BAD);
- return (DW_DLV_ERROR);
- }
-
- is_stmt = !is_stmt;
- break;
- }
-
- case DW_LNS_set_basic_block:{
- if (opcode_length[DW_LNS_set_basic_block] != 0) {
- _dwarf_error(dbg, error,
- DW_DLE_LINE_NUM_OPERANDS_BAD);
- return (DW_DLV_ERROR);
- }
-
- basic_block = true;
- break;
- }
-
- case DW_LNS_const_add_pc:{
- opcode = MAX_LINE_OP_CODE - special_opcode_base;
- address = address + minimum_instruction_length *
- (opcode / line_range);
-
- break;
- }
-
- case DW_LNS_fixed_advance_pc:{
- if (opcode_length[DW_LNS_fixed_advance_pc] != 1) {
- _dwarf_error(dbg, error,
- DW_DLE_LINE_NUM_OPERANDS_BAD);
- return (DW_DLV_ERROR);
- }
-
- READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
- line_ptr, sizeof(Dwarf_Half));
- line_ptr += sizeof(Dwarf_Half);
- address = address + fixed_advance_pc;
- break;
- }
- }
-
- } else if (type == LOP_EXTENDED) {
- Dwarf_Unsigned utmp3;
-
- DECODE_LEB128_UWORD(line_ptr, utmp3)
- instr_length = (Dwarf_Word) utmp3;
- /* Dwarf_Small is a ubyte and the extended opcode
- is a ubyte, though not stated as clearly in
- the 2.0.0 spec as one might hope.
- */
- ext_opcode = *(Dwarf_Small *) line_ptr;
- line_ptr++;
- switch (ext_opcode) {
-
- case DW_LNE_end_sequence:{
- end_sequence = true;
-
- if (dolines) {
- curr_line = (Dwarf_Line)
- _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
- if (curr_line == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- curr_line->li_address = address;
- curr_line->li_addr_line.li_l_data.li_file =
- (Dwarf_Sword) file;
- curr_line->li_addr_line.li_l_data.li_line =
- (Dwarf_Sword) line;
- curr_line->li_addr_line.li_l_data.li_column =
- (Dwarf_Half) column;
- curr_line->li_addr_line.li_l_data.li_is_stmt =
- default_is_stmt;
- curr_line->li_addr_line.li_l_data.
- li_basic_block = basic_block;
- curr_line->li_addr_line.li_l_data.
- li_end_sequence = end_sequence;
- curr_line->li_context = line_context;
- line_count++;
-
- chain_line = (Dwarf_Chain)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (chain_line == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
- chain_line->ch_item = curr_line;
-
- if (head_chain == NULL)
- head_chain = curr_chain = chain_line;
- else {
- curr_chain->ch_next = chain_line;
- curr_chain = chain_line;
- }
- }
-
- address = 0;
- file = 1;
- line = 1;
- column = 0;
- is_stmt = default_is_stmt;
- basic_block = false;
- end_sequence = false;
-
- break;
- }
-
- case DW_LNE_set_address:{
- if (instr_length - 1 == dbg->de_pointer_size) {
- READ_UNALIGNED(dbg, address, Dwarf_Addr,
- line_ptr, dbg->de_pointer_size);
- if (doaddrs) {
- curr_line =
- (Dwarf_Line) _dwarf_get_alloc(dbg,
- DW_DLA_LINE,
- 1);
- if (curr_line == NULL) {
- _dwarf_error(dbg, error,
- DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- curr_line->li_address = address;
- curr_line->li_addr_line.li_offset =
- line_ptr - dbg->de_debug_line;
-
- line_count++;
-
- chain_line = (Dwarf_Chain)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (chain_line == NULL) {
- _dwarf_error(dbg, error,
- DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
- chain_line->ch_item = curr_line;
-
- if (head_chain == NULL)
- head_chain = curr_chain = chain_line;
- else {
- curr_chain->ch_next = chain_line;
- curr_chain = chain_line;
- }
- }
-
- line_ptr += dbg->de_pointer_size;
- } else {
- _dwarf_error(dbg, error,
- DW_DLE_LINE_SET_ADDR_ERROR);
- return (DW_DLV_ERROR);
- }
-
- break;
- }
-
- case DW_LNE_define_file:{
-
- if (dolines) {
- cur_file_entry = (Dwarf_File_Entry)
- _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
- if (cur_file_entry == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- cur_file_entry->fi_file_name =
- (Dwarf_Small *) line_ptr;
- line_ptr =
- line_ptr + strlen((char *) line_ptr) + 1;
-
- cur_file_entry->fi_dir_index =
- (Dwarf_Sword)
- _dwarf_decode_u_leb128(line_ptr,
- &leb128_length);
- line_ptr = line_ptr + leb128_length;
-
- cur_file_entry->fi_time_last_mod =
- _dwarf_decode_u_leb128(line_ptr,
- &leb128_length);
- line_ptr = line_ptr + leb128_length;
-
- cur_file_entry->fi_file_length =
- _dwarf_decode_u_leb128(line_ptr,
- &leb128_length);
- line_ptr = line_ptr + leb128_length;
-
- if (file_entries == NULL)
- file_entries = cur_file_entry;
- else
- prev_file_entry->fi_next = cur_file_entry;
- prev_file_entry = cur_file_entry;
-
- file_entry_count++;
- }
- break;
- }
-
- default:{
- _dwarf_error(dbg, error,
- DW_DLE_LINE_EXT_OPCODE_BAD);
- return (DW_DLV_ERROR);
- }
- }
-
- }
+ int type;
+
+ opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+
+
+ /* 'type' is the output */
+ WHAT_IS_OPCODE(type, opcode, prefix.pf_opcode_base,
+ prefix.pf_opcode_length_table, line_ptr,
+ prefix.pf_std_op_count);
+
+ if (type == LOP_DISCARD) {
+ int oc;
+ int opcnt = prefix.pf_opcode_length_table[opcode];
+
+ for (oc = 0; oc < opcnt; oc++) {
+ /*
+ ** Read and discard operands we don't
+ ** understand.
+ ** arbitrary choice of unsigned read.
+ ** signed read would work as well.
+ */
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ }
+ } else if (type == LOP_SPECIAL) {
+ /* This op code is a special op in the object, no matter
+ that it might fall into the standard op range in this
+ compile. That is, these are special opcodes between
+ opcode_base and MAX_LINE_OP_CODE. (including
+ opcode_base and MAX_LINE_OP_CODE) */
+
+ opcode = opcode - prefix.pf_opcode_base;
+ address = address + prefix.pf_minimum_instruction_length *
+ (opcode / prefix.pf_line_range);
+ line =
+ line + prefix.pf_line_base +
+ opcode % prefix.pf_line_range;
+
+ if (dolines) {
+ curr_line =
+ (Dwarf_Line) _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
+ if (curr_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_line->li_address = address;
+ curr_line->li_addr_line.li_l_data.li_file =
+ (Dwarf_Sword) file;
+ curr_line->li_addr_line.li_l_data.li_line =
+ (Dwarf_Sword) line;
+ curr_line->li_addr_line.li_l_data.li_column =
+ (Dwarf_Half) column;
+ curr_line->li_addr_line.li_l_data.li_is_stmt = is_stmt;
+ curr_line->li_addr_line.li_l_data.li_basic_block =
+ basic_block;
+ curr_line->li_addr_line.li_l_data.li_end_sequence =
+ curr_line->li_addr_line.li_l_data.
+ li_epilogue_begin = epilogue_begin;
+ curr_line->li_addr_line.li_l_data.li_prologue_end =
+ prologue_end;
+ curr_line->li_addr_line.li_l_data.li_isa = isa;
+ curr_line->li_context = line_context;
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_line->ch_item = curr_line;
+
+ if (head_chain == NULL)
+ head_chain = curr_chain = chain_line;
+ else {
+ curr_chain->ch_next = chain_line;
+ curr_chain = chain_line;
+ }
+ }
+
+ basic_block = false;
+ } else if (type == LOP_STANDARD) {
+ switch (opcode) {
+
+ case DW_LNS_copy:{
+ if (dolines) {
+
+ curr_line =
+ (Dwarf_Line) _dwarf_get_alloc(dbg,
+ DW_DLA_LINE,
+ 1);
+ if (curr_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_line->li_address = address;
+ curr_line->li_addr_line.li_l_data.li_file =
+ (Dwarf_Sword) file;
+ curr_line->li_addr_line.li_l_data.li_line =
+ (Dwarf_Sword) line;
+ curr_line->li_addr_line.li_l_data.li_column =
+ (Dwarf_Half) column;
+ curr_line->li_addr_line.li_l_data.li_is_stmt =
+ is_stmt;
+ curr_line->li_addr_line.li_l_data.
+ li_basic_block = basic_block;
+ curr_line->li_addr_line.li_l_data.
+ li_end_sequence = end_sequence;
+ curr_line->li_context = line_context;
+ curr_line->li_addr_line.li_l_data.
+ li_epilogue_begin = epilogue_begin;
+ curr_line->li_addr_line.li_l_data.
+ li_prologue_end = prologue_end;
+ curr_line->li_addr_line.li_l_data.li_isa = isa;
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_line->ch_item = curr_line;
+ if (head_chain == NULL)
+ head_chain = curr_chain = chain_line;
+ else {
+ curr_chain->ch_next = chain_line;
+ curr_chain = chain_line;
+ }
+ }
+
+ basic_block = false;
+ prologue_end = false;
+ epilogue_begin = false;
+ break;
+ }
+
+ case DW_LNS_advance_pc:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ leb128_num = (Dwarf_Word) utmp2;
+ address =
+ address +
+ prefix.pf_minimum_instruction_length *
+ leb128_num;
+ break;
+ }
+
+ case DW_LNS_advance_line:{
+ Dwarf_Signed stmp;
+
+ DECODE_LEB128_SWORD(line_ptr, stmp);
+ advance_line = (Dwarf_Sword) stmp;
+ line = line + advance_line;
+ break;
+ }
+
+ case DW_LNS_set_file:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ file = (Dwarf_Word) utmp2;
+ break;
+ }
+
+ case DW_LNS_set_column:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ column = (Dwarf_Word) utmp2;
+ break;
+ }
+
+ case DW_LNS_negate_stmt:{
+
+ is_stmt = !is_stmt;
+ break;
+ }
+
+ case DW_LNS_set_basic_block:{
+
+ basic_block = true;
+ break;
+ }
+
+ case DW_LNS_const_add_pc:{
+ opcode = MAX_LINE_OP_CODE - prefix.pf_opcode_base;
+ address = address +
+ prefix.pf_minimum_instruction_length * (opcode /
+ prefix.
+ pf_line_range);
+ break;
+ }
+
+ case DW_LNS_fixed_advance_pc:{
+
+ READ_UNALIGNED(dbg, fixed_advance_pc, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ line_ptr += sizeof(Dwarf_Half);
+ address = address + fixed_advance_pc;
+ break;
+ }
+
+ /* New in DWARF3 */
+ case DW_LNS_set_prologue_end:{
+
+ prologue_end = true;
+ break;
+
+
+ }
+ /* New in DWARF3 */
+ case DW_LNS_set_epilogue_begin:{
+ epilogue_begin = true;
+ break;
+ }
+
+ /* New in DWARF3 */
+ case DW_LNS_set_isa:{
+ Dwarf_Unsigned utmp2;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp2);
+ isa = utmp2;
+ if (isa != utmp2) {
+ /* The value of the isa did not fit in our
+ local so we record it wrong. declare an
+ error. */
+ dwarf_free_line_table_prefix(&prefix);
+
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
+ break;
+ }
+ }
+
+ } else if (type == LOP_EXTENDED) {
+ Dwarf_Unsigned utmp3;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp3);
+ instr_length = (Dwarf_Word) utmp3;
+ /* Dwarf_Small is a ubyte and the extended opcode is a
+ ubyte, though not stated as clearly in the 2.0.0 spec as
+ one might hope. */
+ ext_opcode = *(Dwarf_Small *) line_ptr;
+ line_ptr++;
+ switch (ext_opcode) {
+
+ case DW_LNE_end_sequence:{
+ end_sequence = true;
+
+ if (dolines) {
+ curr_line = (Dwarf_Line)
+ _dwarf_get_alloc(dbg, DW_DLA_LINE, 1);
+ if (curr_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_line->li_address = address;
+ curr_line->li_addr_line.li_l_data.li_file =
+ (Dwarf_Sword) file;
+ curr_line->li_addr_line.li_l_data.li_line =
+ (Dwarf_Sword) line;
+ curr_line->li_addr_line.li_l_data.li_column =
+ (Dwarf_Half) column;
+ curr_line->li_addr_line.li_l_data.li_is_stmt =
+ prefix.pf_default_is_stmt;
+ curr_line->li_addr_line.li_l_data.
+ li_basic_block = basic_block;
+ curr_line->li_addr_line.li_l_data.
+ li_end_sequence = end_sequence;
+ curr_line->li_context = line_context;
+ curr_line->li_addr_line.li_l_data.
+ li_epilogue_begin = epilogue_begin;
+ curr_line->li_addr_line.li_l_data.
+ li_prologue_end = prologue_end;
+ curr_line->li_addr_line.li_l_data.li_isa = isa;
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_line->ch_item = curr_line;
+
+ if (head_chain == NULL)
+ head_chain = curr_chain = chain_line;
+ else {
+ curr_chain->ch_next = chain_line;
+ curr_chain = chain_line;
+ }
+ }
+
+ address = 0;
+ file = 1;
+ line = 1;
+ column = 0;
+ is_stmt = prefix.pf_default_is_stmt;
+ basic_block = false;
+ end_sequence = false;
+ prologue_end = false;
+ epilogue_begin = false;
+
+
+ break;
+ }
+
+ case DW_LNE_set_address:{
+ {
+ READ_UNALIGNED(dbg, address, Dwarf_Addr,
+ line_ptr, address_size);
+ if (doaddrs) {
+ curr_line =
+ (Dwarf_Line) _dwarf_get_alloc(dbg,
+ DW_DLA_LINE,
+ 1);
+ if (curr_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error,
+ DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ curr_line->li_address = address;
+ curr_line->li_addr_line.li_offset =
+ line_ptr - dbg->de_debug_line.dss_data;
+
+ line_count++;
+
+ chain_line = (Dwarf_Chain)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_line == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error,
+ DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ chain_line->ch_item = curr_line;
+
+ if (head_chain == NULL)
+ head_chain = curr_chain = chain_line;
+ else {
+ curr_chain->ch_next = chain_line;
+ curr_chain = chain_line;
+ }
+ }
+
+ line_ptr += address_size;
+ }
+
+ break;
+ }
+
+ case DW_LNE_define_file:{
+
+ if (dolines) {
+ cur_file_entry = (Dwarf_File_Entry)
+ _dwarf_get_alloc(dbg, DW_DLA_FILE_ENTRY, 1);
+ if (cur_file_entry == NULL) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ cur_file_entry->fi_file_name =
+ (Dwarf_Small *) line_ptr;
+ line_ptr =
+ line_ptr + strlen((char *) line_ptr) + 1;
+
+ cur_file_entry->fi_dir_index = (Dwarf_Sword)
+ _dwarf_decode_u_leb128(line_ptr,
+ &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ cur_file_entry->fi_time_last_mod =
+ _dwarf_decode_u_leb128(line_ptr,
+ &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ cur_file_entry->fi_file_length =
+ _dwarf_decode_u_leb128(line_ptr,
+ &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+
+ if (file_entries == NULL)
+ file_entries = cur_file_entry;
+ else
+ prev_file_entry->fi_next = cur_file_entry;
+ prev_file_entry = cur_file_entry;
+
+ file_entry_count++;
+ }
+ break;
+ }
+
+ default:{
+ /* This is an extended op code we do not know about,
+ other than we know now many bytes it is
+ and the op code and the bytes of operand. */
+ Dwarf_Unsigned remaining_bytes = instr_length -1;
+ if(instr_length < 1 || remaining_bytes > DW_LNE_LEN_MAX) {
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error,
+ DW_DLE_LINE_EXT_OPCODE_BAD);
+ return (DW_DLV_ERROR);
+ }
+ line_ptr += remaining_bytes;
+ break;
+ }
+ }
+
+ }
}
block_line = (Dwarf_Line *)
- _dwarf_get_alloc(dbg, DW_DLA_LIST, line_count);
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, line_count);
if (block_line == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
+ dwarf_free_line_table_prefix(&prefix);
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
}
curr_chain = head_chain;
for (i = 0; i < line_count; i++) {
- *(block_line + i) = curr_chain->ch_item;
- head_chain = curr_chain;
- curr_chain = curr_chain->ch_next;
- dwarf_dealloc(dbg, head_chain, DW_DLA_CHAIN);
+ *(block_line + i) = curr_chain->ch_item;
+ head_chain = curr_chain;
+ curr_chain = curr_chain->ch_next;
+ dwarf_dealloc(dbg, head_chain, DW_DLA_CHAIN);
}
line_context->lc_file_entries = file_entries;
line_context->lc_file_entry_count = file_entry_count;
- line_context->lc_include_directories = include_directories;
line_context->lc_include_directories_count =
- include_directories_count;
+ prefix.pf_include_directories_count;
+ if (prefix.pf_include_directories_count > 0) {
+ /* This gets a pointer to the *first* include dir. The others
+ follow directly with the standard DWARF2/3 NUL byte
+ following the last. */
+ line_context->lc_include_directories =
+ prefix.pf_include_directories[0];
+ }
+
line_context->lc_line_count = line_count;
line_context->lc_compilation_directory = comp_dir;
+ line_context->lc_version_number = prefix.pf_version;
line_context->lc_dbg = dbg;
*count = line_count;
*linebuf = block_line;
+ dwarf_free_line_table_prefix(&prefix);
return (DW_DLV_OK);
}
int
dwarf_srclines(Dwarf_Die die,
- Dwarf_Line ** linebuf,
- Dwarf_Signed * linecount, Dwarf_Error * error)
+ Dwarf_Line ** linebuf,
+ Dwarf_Signed * linecount, Dwarf_Error * error)
{
- Dwarf_Signed count;
- int res;
-
- res = _dwarf_internal_srclines(die, linebuf,
- &count, /* addrlist= */ false,
- /* linelist= */ true, error);
+ Dwarf_Signed count = 0;
+ int res = _dwarf_internal_srclines(die, linebuf, &count,
+ /* addrlist= */ false,
+ /* linelist= */ true, error);
if (res != DW_DLV_OK) {
- return res;
+ return res;
}
*linecount = count;
return res;
@@ -1105,28 +1035,46 @@ dwarf_srclines(Dwarf_Die die,
-
+/* Every line table entry (except DW_DLE_end_sequence,
+ which is returned using dwarf_lineendsequence())
+ potentially has the begin-statement
+ flag marked 'on'. This returns thru *return_bool,
+ the begin-statement flag.
+*/
int
dwarf_linebeginstatement(Dwarf_Line line,
- Dwarf_Bool * return_bool, Dwarf_Error * error)
+ Dwarf_Bool * return_bool, Dwarf_Error * error)
{
if (line == NULL || return_bool == 0) {
- _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
}
*return_bool = (line->li_addr_line.li_l_data.li_is_stmt);
return DW_DLV_OK;
}
+/* At the end of any contiguous line-table there may be
+ a DW_LNE_end_sequence operator.
+ This returns non-zero thru *return_bool
+ if and only if this 'line' entry was a DW_LNE_end_sequence.
+
+ Within a compilation unit or function there may be multiple
+ line tables, each ending with a DW_LNE_end_sequence.
+ Each table describes a contiguous region.
+ Because compilers may split function code up in arbitrary ways
+ compilers may need to emit multiple contigous regions (ie
+ line tables) for a single function.
+ See the DWARF3 spec section 6.2.
+*/
int
dwarf_lineendsequence(Dwarf_Line line,
- Dwarf_Bool * return_bool, Dwarf_Error * error)
+ Dwarf_Bool * return_bool, Dwarf_Error * error)
{
if (line == NULL) {
- _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
}
*return_bool = (line->li_addr_line.li_l_data.li_end_sequence);
@@ -1134,27 +1082,64 @@ dwarf_lineendsequence(Dwarf_Line line,
}
+/* Each 'line' entry has a line-number.
+ If the entry is a DW_LNE_end_sequence the line-number is
+ meaningless (see dwarf_lineendsequence(), just above).
+*/
int
dwarf_lineno(Dwarf_Line line,
- Dwarf_Unsigned * ret_lineno, Dwarf_Error * error)
+ Dwarf_Unsigned * ret_lineno, Dwarf_Error * error)
{
if (line == NULL || ret_lineno == 0) {
- _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
}
*ret_lineno = (line->li_addr_line.li_l_data.li_line);
return DW_DLV_OK;
}
+/* Each 'line' entry has a file-number, and index into the file table.
+ If the entry is a DW_LNE_end_sequence the index is
+ meaningless (see dwarf_lineendsequence(), just above).
+ The file number returned is an index into the file table
+ produced by dwarf_srcfiles(), but care is required: the
+ li_file begins with 1 for real files, so that the li_file returned here
+ is 1 greater than its index into the dwarf_srcfiles() output array.
+ And entries from DW_LNE_define_file don't appear in
+ the dwarf_srcfiles() output so file indexes from here may exceed
+ the size of the dwarf_srcfiles() output array size.
+*/
+int
+dwarf_line_srcfileno(Dwarf_Line line,
+ Dwarf_Unsigned * ret_fileno, Dwarf_Error * error)
+{
+ if (line == NULL || ret_fileno == 0) {
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
+ }
+ /* li_file must be <= line->li_context->lc_file_entry_count else it
+ is trash. li_file 0 means not attributable to any source file
+ per dwarf2/3 spec. */
+
+ *ret_fileno = (line->li_addr_line.li_l_data.li_file);
+ return DW_DLV_OK;
+}
+
+/* Each 'line' entry has a line-address.
+ If the entry is a DW_LNE_end_sequence the adddress
+ is one-beyond the last address this contigous region
+ covers, so the address is not inside the region,
+ but is just outside it.
+*/
int
dwarf_lineaddr(Dwarf_Line line,
- Dwarf_Addr * ret_lineaddr, Dwarf_Error * error)
+ Dwarf_Addr * ret_lineaddr, Dwarf_Error * error)
{
if (line == NULL || ret_lineaddr == 0) {
- _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
}
*ret_lineaddr = (line->li_address);
@@ -1162,18 +1147,27 @@ dwarf_lineaddr(Dwarf_Line line,
}
+/* Each 'line' entry has a column-within-line (offset
+ within the line) where the
+ source text begins.
+ If the entry is a DW_LNE_end_sequence the line-number is
+ meaningless (see dwarf_lineendsequence(), just above).
+ Lines of text begin at column 1. The value 0
+ means the line begins at the left edge of the line.
+ (See the DWARF3 spec, section 6.2.2).
+*/
int
dwarf_lineoff(Dwarf_Line line,
- Dwarf_Signed * ret_lineoff, Dwarf_Error * error)
+ Dwarf_Signed * ret_lineoff, Dwarf_Error * error)
{
if (line == NULL || ret_lineoff == 0) {
- _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
}
*ret_lineoff =
- (line->li_addr_line.li_l_data.li_column ==
- 0 ? -1 : line->li_addr_line.li_l_data.li_column);
+ (line->li_addr_line.li_l_data.li_column ==
+ 0 ? -1 : line->li_addr_line.li_l_data.li_column);
return DW_DLV_OK;
}
@@ -1181,135 +1175,149 @@ dwarf_lineoff(Dwarf_Line line,
int
dwarf_linesrc(Dwarf_Line line, char **ret_linesrc, Dwarf_Error * error)
{
- Dwarf_Signed i;
+ Dwarf_Signed i = 0;
Dwarf_File_Entry file_entry;
- Dwarf_Small *name_buffer;
- Dwarf_Small *include_directories;
- Dwarf_Debug dbg;
- unsigned int comp_dir_len;
+ Dwarf_Small *name_buffer = 0;
+ Dwarf_Small *include_directories = 0;
+ Dwarf_Small include_direc_full_path = 0;
+ Dwarf_Small file_name_full_path = 0;
+ Dwarf_Debug dbg = 0;
+ unsigned int comp_dir_len = 0;
if (line == NULL) {
- _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
}
if (line->li_context == NULL) {
- _dwarf_error(NULL, error, DW_DLE_LINE_CONTEXT_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_LINE_CONTEXT_NULL);
+ return (DW_DLV_ERROR);
}
dbg = line->li_context->lc_dbg;
if (line->li_addr_line.li_l_data.li_file >
- line->li_context->lc_file_entry_count) {
- _dwarf_error(dbg, error, DW_DLE_LINE_FILE_NUM_BAD);
- return (DW_DLV_ERROR);
+ line->li_context->lc_file_entry_count) {
+ _dwarf_error(dbg, error, DW_DLE_LINE_FILE_NUM_BAD);
+ return (DW_DLV_ERROR);
}
+ if (line->li_addr_line.li_l_data.li_file == 0) {
+ /* No file name known: see dwarf2/3 spec. */
+ _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME);
+ return (DW_DLV_ERROR);
+ }
file_entry = line->li_context->lc_file_entries;
+ /* ASSERT: li_file > 0, dwarf correctness issue, see line table
+ definition of dwarf2/3 spec. */
+ /* Example: if li_file is 2 and lc_file_entry_count is 3,
+ file_entry is file 3 (1 based), aka 2( 0 based) file_entry->next
+ is file 2 (1 based), aka 1( 0 based) file_entry->next->next is
+ file 1 (1 based), aka 0( 0 based) file_entry->next->next->next
+ is NULL.
+
+ and this loop finds the file_entry we need (2 (1 based) in this
+ case). Because lc_file_entries are in reverse order and
+ effectively zero based as a count whereas li_file is 1 based. */
for (i = line->li_addr_line.li_l_data.li_file - 1; i > 0; i--)
- file_entry = file_entry->fi_next;
+ file_entry = file_entry->fi_next;
if (file_entry->fi_file_name == NULL) {
- _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME);
- return (DW_DLV_ERROR);
+ _dwarf_error(dbg, error, DW_DLE_NO_FILE_NAME);
+ return (DW_DLV_ERROR);
}
- if (*(char *) file_entry->fi_file_name == '/') {
- *ret_linesrc = ((char *) file_entry->fi_file_name);
- return DW_DLV_OK;
+ file_name_full_path = file_name_is_full_path(file_entry->fi_file_name);
+ if (file_name_full_path) {
+ *ret_linesrc = ((char *) file_entry->fi_file_name);
+ return DW_DLV_OK;
}
if (file_entry->fi_dir_index == 0) {
- /* dir_index of 0 means that the compilation was in the
- 'current directory of compilation' */
- if (line->li_context->lc_compilation_directory == NULL) {
- /* we don't actually *have* a current directory of
- compilation: DW_AT_comp_dir was not present Rather than
- emitting DW_DLE_NO_COMP_DIR lets just make an empty name
- here. In other words, do the best we can with what we do
- have instead of reporting an error. _dwarf_error(dbg,
- error, DW_DLE_NO_COMP_DIR); return(DW_DLV_ERROR); */
- comp_dir_len = 0;
- } else {
- comp_dir_len = strlen((char *)
- (line->li_context->
- lc_compilation_directory));
- }
-
- name_buffer =
- _dwarf_get_alloc(line->li_context->lc_dbg, DW_DLA_STRING,
- comp_dir_len + 1 +
- strlen((char *) file_entry->fi_file_name) +
- 1);
- if (name_buffer == NULL) {
- _dwarf_error(line->li_context->lc_dbg, error,
- DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- if (comp_dir_len > 0) {
- /* if comp_dir_len is 0 we do not want to put a / in front
- of the fi_file_name as we just don't know anything. */
- strcpy((char *) name_buffer,
- (char *) (line->li_context->
- lc_compilation_directory));
- strcat((char *) name_buffer, "/");
- }
- strcat((char *) name_buffer, (char *) file_entry->fi_file_name);
- *ret_linesrc = ((char *) name_buffer);
- return DW_DLV_OK;
+ /* dir_index of 0 means that the compilation was in the
+ 'current directory of compilation' */
+ if (line->li_context->lc_compilation_directory == NULL) {
+ /* we don't actually *have* a current directory of
+ compilation: DW_AT_comp_dir was not present Rather than
+ emitting DW_DLE_NO_COMP_DIR lets just make an empty name
+ here. In other words, do the best we can with what we do
+ have instead of reporting an error. _dwarf_error(dbg,
+ error, DW_DLE_NO_COMP_DIR); return(DW_DLV_ERROR); */
+ comp_dir_len = 0;
+ } else {
+ comp_dir_len = strlen((char *)
+ (line->li_context->
+ lc_compilation_directory));
+ }
+
+ name_buffer =
+ _dwarf_get_alloc(line->li_context->lc_dbg, DW_DLA_STRING,
+ comp_dir_len + 1 +
+ strlen((char *) file_entry->fi_file_name) +
+ 1);
+ if (name_buffer == NULL) {
+ _dwarf_error(line->li_context->lc_dbg, error,
+ DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (comp_dir_len > 0) {
+ /* if comp_dir_len is 0 we do not want to put a / in front
+ of the fi_file_name as we just don't know anything. */
+ strcpy((char *) name_buffer,
+ (char *) (line->li_context->
+ lc_compilation_directory));
+ strcat((char *) name_buffer, "/");
+ }
+ strcat((char *) name_buffer, (char *) file_entry->fi_file_name);
+ *ret_linesrc = ((char *) name_buffer);
+ return DW_DLV_OK;
}
if (file_entry->fi_dir_index >
- line->li_context->lc_include_directories_count) {
- _dwarf_error(dbg, error, DW_DLE_INCL_DIR_NUM_BAD);
- return (DW_DLV_ERROR);
+ line->li_context->lc_include_directories_count) {
+ _dwarf_error(dbg, error, DW_DLE_INCL_DIR_NUM_BAD);
+ return (DW_DLV_ERROR);
}
include_directories = line->li_context->lc_include_directories;
for (i = file_entry->fi_dir_index - 1; i > 0; i--)
- include_directories += strlen((char *) include_directories) + 1;
+ include_directories += strlen((char *) include_directories) + 1;
if (line->li_context->lc_compilation_directory) {
- comp_dir_len = strlen((char *)
- (line->li_context->
- lc_compilation_directory));
+ comp_dir_len = strlen((char *)
+ (line->li_context->lc_compilation_directory));
} else {
- /* No DW_AT_comp_dir present. Do the best we can without it. */
- comp_dir_len = 0;
+ /* No DW_AT_comp_dir present. Do the best we can without it. */
+ comp_dir_len = 0;
}
+ include_direc_full_path = file_name_is_full_path(include_directories);
name_buffer = _dwarf_get_alloc(dbg, DW_DLA_STRING,
- (*include_directories == '/' ?
- 0 : comp_dir_len + 1) +
- strlen((char *) include_directories)
- + 1 +
- strlen((char *) file_entry->
- fi_file_name) + 1);
+ (include_direc_full_path ? 0 : comp_dir_len + 1) +
+ strlen((char *)include_directories) + 1 +
+ strlen((char *)file_entry->fi_file_name) + 1);
if (name_buffer == NULL) {
- _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- if (*include_directories != '/') {
- if (comp_dir_len > 0) {
- strcpy((char *) name_buffer,
- (char *) line->li_context->lc_compilation_directory);
- /* Who provides the / needed after the compilation
- directory? */
- if (name_buffer[comp_dir_len - 1] != '/') {
- /* Here we provide the / separator */
- name_buffer[comp_dir_len] = '/'; /* overwrite
- previous nul
- terminator
- with needed
- / */
- name_buffer[comp_dir_len + 1] = 0;
- }
- }
+ _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ if (!include_direc_full_path) {
+ if (comp_dir_len > 0) {
+ strcpy((char *)name_buffer,
+ (char *)line->li_context->lc_compilation_directory);
+ /* Who provides the / needed after the compilation
+ directory? */
+ if (!is_path_separator(name_buffer[comp_dir_len - 1])) {
+ /* Here we provide the / separator. It
+ should work ok for Windows */
+ /* Overwrite previous nul terminator with needed / */
+ name_buffer[comp_dir_len] = '/';
+ name_buffer[comp_dir_len + 1] = 0;
+ }
+ }
} else {
- strcpy((char *) name_buffer, "");
+ strcpy((char *) name_buffer, "");
}
strcat((char *) name_buffer, (char *) include_directories);
strcat((char *) name_buffer, "/");
@@ -1318,23 +1326,25 @@ dwarf_linesrc(Dwarf_Line line, char **ret_linesrc, Dwarf_Error * error)
return DW_DLV_OK;
}
-
+/* Every line table entry potentially has the basic-block-start
+ flag marked 'on'. This returns thru *return_bool,
+ the basic-block-start flag.
+*/
int
dwarf_lineblock(Dwarf_Line line,
- Dwarf_Bool * return_bool, Dwarf_Error * error)
+ Dwarf_Bool * return_bool, Dwarf_Error * error)
{
if (line == NULL) {
- _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
- return (DW_DLV_ERROR);
+ _dwarf_error(NULL, error, DW_DLE_DWARF_LINE_NULL);
+ return (DW_DLV_ERROR);
}
-
*return_bool = (line->li_addr_line.li_l_data.li_basic_block);
return DW_DLV_OK;
}
-#if 0 /* Ignore this. This needs major
- re-work. */
+#if 0 /* Ignore this. This needs major
+ re-work. */
/*
This routine works by looking for exact matches between
the current line address and pc, and crossovers from
@@ -1346,10 +1356,10 @@ dwarf_lineblock(Dwarf_Line line,
*/
int
dwarf_pclines(Dwarf_Debug dbg,
- Dwarf_Addr pc,
- Dwarf_Line ** linebuf,
- Dwarf_Signed slide,
- Dwarf_Signed * linecount, Dwarf_Error * error)
+ Dwarf_Addr pc,
+ Dwarf_Line ** linebuf,
+ Dwarf_Signed slide,
+ Dwarf_Signed * linecount, Dwarf_Error * error)
{
/*
Scans the line matrix for the current cu to which a pointer
@@ -1359,29 +1369,29 @@ dwarf_pclines(Dwarf_Debug dbg,
/*
These flags are for efficiency reasons. Check_line is true
- initially, but set false when the address of the current line
- is greater than pc. It is set true only when the address of the
- current line falls below pc. This assumes that addresses
- within the same segment increase, and we are only interested in
- the switch from a less than pc address to a greater than.
- First_line is set true initially, but set false after the first
- line is scanned. This is to prevent looking at the address of
- previous line when slide is DW_DLS_BACKWARD, and the first line
- is being scanned. */
+ initially, but set false when the address of the current line is
+ greater than pc. It is set true only when the address of the
+ current line falls below pc. This assumes that addresses within
+ the same segment increase, and we are only interested in the
+ switch from a less than pc address to a greater than. First_line
+ is set true initially, but set false after the first line is
+ scanned. This is to prevent looking at the address of previous
+ line when slide is DW_DLS_BACKWARD, and the first line is being
+ scanned. */
Dwarf_Bool check_line, first_line;
/*
- Diff tracks the smallest difference a line address and the
- input pc value. */
+ Diff tracks the smallest difference a line address and the input
+ pc value. */
Dwarf_Signed diff, i;
/*
For the slide = DW_DLS_BACKWARD case, pc_less is the value of
the address of the line immediately preceding the first line
- that has value greater than pc. For the slide = DW_DLS_FORWARD
+ that has value greater than pc. For the slide = DW_DLS_FORWARD
case, pc_more is the values of address for the first line that
- is greater than pc. Diff is the difference between either of
- the these values and pc. */
+ is greater than pc. Diff is the difference between either of the
+ these values and pc. */
Dwarf_Addr pc_less, pc_more;
/*
@@ -1404,88 +1414,88 @@ dwarf_pclines(Dwarf_Debug dbg,
for (i = 0; i < dbg->de_cu_line_count; i++) {
- line = *(dbg->de_cu_line_ptr + i);
- prev_line = first_line ? NULL : *(dbg->de_cu_line_ptr + i - 1);
-
- if (line->li_address == pc) {
- chain_ptr = (struct chain *)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (chain_ptr == NULL) {
- _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- chain_ptr->line = line;
- chain_ptr->diff = diff = 0;
- chain_ptr->next = chain_head;
- chain_head = chain_ptr;
- } else
- /*
- Look for crossover from less than pc address to greater
- than. */
- if (check_line && line->li_address > pc &&
- (first_line ? 0 : prev_line->li_address) < pc)
-
- if (slide == DW_DLS_BACKWARD && !first_line) {
- pc_less = prev_line->li_address;
- if (pc - pc_less <= diff) {
- chain_ptr = (struct chain *)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (chain_ptr == NULL) {
- _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- chain_ptr->line = prev_line;
- chain_ptr->diff = diff = pc - pc_less;
- chain_ptr->next = chain_head;
- chain_head = chain_ptr;
- }
- check_line = false;
- } else if (slide == DW_DLS_FORWARD) {
- pc_more = line->li_address;
- if (pc_more - pc <= diff) {
- chain_ptr = (struct chain *)
- _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
- if (chain_ptr == NULL) {
- _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
- }
-
- chain_ptr->line = line;
- chain_ptr->diff = diff = pc_more - pc;
- chain_ptr->next = chain_head;
- chain_head = chain_ptr;
- }
- check_line = false;
- } else
- /* Check addresses only when they go */
- /* below pc. */
- if (line->li_address < pc)
- check_line = true;
-
- first_line = false;
+ line = *(dbg->de_cu_line_ptr + i);
+ prev_line = first_line ? NULL : *(dbg->de_cu_line_ptr + i - 1);
+
+ if (line->li_address == pc) {
+ chain_ptr = (struct chain *)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_ptr == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ chain_ptr->line = line;
+ chain_ptr->diff = diff = 0;
+ chain_ptr->next = chain_head;
+ chain_head = chain_ptr;
+ } else
+ /*
+ Look for crossover from less than pc address to greater
+ than. */
+ if (check_line && line->li_address > pc &&
+ (first_line ? 0 : prev_line->li_address) < pc)
+
+ if (slide == DW_DLS_BACKWARD && !first_line) {
+ pc_less = prev_line->li_address;
+ if (pc - pc_less <= diff) {
+ chain_ptr = (struct chain *)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_ptr == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ chain_ptr->line = prev_line;
+ chain_ptr->diff = diff = pc - pc_less;
+ chain_ptr->next = chain_head;
+ chain_head = chain_ptr;
+ }
+ check_line = false;
+ } else if (slide == DW_DLS_FORWARD) {
+ pc_more = line->li_address;
+ if (pc_more - pc <= diff) {
+ chain_ptr = (struct chain *)
+ _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
+ if (chain_ptr == NULL) {
+ _dwarf_error(NULL, error, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+
+ chain_ptr->line = line;
+ chain_ptr->diff = diff = pc_more - pc;
+ chain_ptr->next = chain_head;
+ chain_head = chain_ptr;
+ }
+ check_line = false;
+ } else
+ /* Check addresses only when they go */
+ /* below pc. */
+ if (line->li_address < pc)
+ check_line = true;
+
+ first_line = false;
}
chain_count = 0;
for (chain_ptr = chain_head; chain_ptr != NULL;
- chain_ptr = chain_ptr->next)
- if (chain_ptr->diff == diff)
- chain_count++;
+ chain_ptr = chain_ptr->next)
+ if (chain_ptr->diff == diff)
+ chain_count++;
pc_line_buf = pc_line = (Dwarf_Line)
- _dwarf_get_alloc(dbg, DW_DLA_LIST, chain_count);
+ _dwarf_get_alloc(dbg, DW_DLA_LIST, chain_count);
for (chain_ptr = chain_head; chain_ptr != NULL;
- chain_ptr = chain_ptr->next)
- if (chain_ptr->diff == diff) {
- *pc_line = chain_ptr->line;
- pc_line++;
- }
+ chain_ptr = chain_ptr->next)
+ if (chain_ptr->diff == diff) {
+ *pc_line = chain_ptr->line;
+ pc_line++;
+ }
for (chain_ptr = chain_head; chain_ptr != NULL;) {
- chain_head = chain_ptr;
- chain_ptr = chain_ptr->next;
- dwarf_dealloc(dbg, chain_head, DW_DLA_CHAIN);
+ chain_head = chain_ptr;
+ chain_ptr = chain_ptr->next;
+ dwarf_dealloc(dbg, chain_head, DW_DLA_CHAIN);
}
*linebuf = pc_line_buf;
@@ -1494,55 +1504,448 @@ dwarf_pclines(Dwarf_Debug dbg,
#endif
+
/*
- Return DW_DLV_OK or, if error,
- DW_DLV_ERROR.
+ It's impossible for callers of dwarf_srclines() to get to and
+ free all the resources (in particular, the li_context and its
+ lc_file_entries).
+ So this function, new July 2005, does it.
+*/
+
+void
+dwarf_srclines_dealloc(Dwarf_Debug dbg, Dwarf_Line * linebuf,
+ Dwarf_Signed count)
+{
+
+ Dwarf_Signed i = 0;
+ struct Dwarf_Line_Context_s *context = 0;
+
+ if (count > 0) {
+ /* All these entries share a single context */
+ context = linebuf[0]->li_context;
+ }
+ for (i = 0; i < count; ++i) {
+ dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE);
+ }
+ dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);
- Thru pointers, return 2 arrays and a count
- for rqs.
+ if (context) {
+ Dwarf_File_Entry fe = context->lc_file_entries;
+
+ while (fe) {
+ Dwarf_File_Entry fenext = fe->fi_next;
+
+ dwarf_dealloc(dbg, fe, DW_DLA_FILE_ENTRY);
+ fe = fenext;
+ }
+ dwarf_dealloc(dbg, context, DW_DLA_LINE_CONTEXT);
+ }
+
+ return;
+}
+
+/* Operand counts per standard operand.
+ The initial zero is for DW_LNS_copy.
+ This is an economical way to verify we understand the table
+ of standard-opcode-lengths in the line table prologue. */
+#define STANDARD_OPERAND_COUNT_DWARF2 9
+#define STANDARD_OPERAND_COUNT_DWARF3 12
+static unsigned char
+ dwarf_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = {
+ /* DWARF2 */
+ 0,
+ 1, 1, 1, 1,
+ 0, 0, 0,
+ 1,
+ /* Following are new for DWARF3. */
+ 0, 0, 1
+};
+
+/* We have a normal standard opcode base, but
+ an arm compiler emitted a non-standard table!
+ This could lead to problems...
+ ARM C/C++ Compiler, RVCT4.0 [Build 4
+ 00] seems to get the table wrong . */
+static unsigned char
+dwarf_arm_standard_opcode_operand_count[STANDARD_OPERAND_COUNT_DWARF3] = {
+ /* DWARF2 */
+ 0,
+ 1, 1, 1, 1,
+ 0, 0, 0,
+ 0, /* <<< --- this is wrong */
+ /* Following are new for DWARF3. */
+ 0, 0, 1
+};
+
+static void
+print_header_issue(Dwarf_Debug dbg,
+ char *specific_msg,
+ Dwarf_Small *data_start,
+ int *err_count_out)
+{
+ if(!err_count_out)
+ return;
+ printf("*** DWARF CHECK: "
+ "line table header: %s",
+ specific_msg);
+ if( data_start >= dbg->de_debug_line.dss_data &&
+ (data_start < (dbg->de_debug_line.dss_data +
+ dbg->de_debug_line.dss_size))) {
+ Dwarf_Unsigned off = data_start - dbg->de_debug_line.dss_data;
+ printf(" at .debug_line section offset 0x%" DW_PR_DUx
+ " ( %" DW_PR_DUu " ) ",
+ off,off);
+ } else {
+ printf(" (unknown section location) ");
+ }
+ printf("***\n");
+ *err_count_out += 1;
+}
+
+
+
+/* Common line table prefix reading code.
+ Returns DW_DLV_OK, DW_DLV_ERROR.
+ DW_DLV_NO_ENTRY cannot be returned, but callers should
+ assume it is possible.
+
+ The prefix_out area must be initialized properly before calling this.
+
+ Has the side effect of allocating arrays which
+ must be freed (see the Line_Table_Prefix_s struct which
+ holds the pointers to space we allocate here).
+
+ bogus_bytes_ptr and bogus_bytes are output values which
+ let a print-program notify the user of some surprising bytes
+ after a line table header and before the line table instructions.
+ These can be ignored unless one is printing.
+ And are ignored if NULL passed as the pointer.
+*/
+
+/* err_count_out may be NULL, in which case we
+ make no attempt to count checking-type errors.
+ Checking-type errors do not stop us, we just report them.
*/
int
-_dwarf_line_address_offsets(Dwarf_Debug dbg,
- Dwarf_Die die,
- Dwarf_Addr ** addrs,
- Dwarf_Off ** offs,
- Dwarf_Unsigned * returncount,
- Dwarf_Error * err)
+dwarf_read_line_table_prefix(Dwarf_Debug dbg,
+ Dwarf_Small * data_start,
+ Dwarf_Unsigned data_length,
+ Dwarf_Small ** updated_data_start_out,
+ struct Line_Table_Prefix_s *prefix_out,
+ Dwarf_Small ** bogus_bytes_ptr,
+ Dwarf_Unsigned *bogus_bytes,
+ Dwarf_Error * err,
+ int *err_count_out)
{
- Dwarf_Addr *laddrs;
- Dwarf_Off *loffsets;
- Dwarf_Signed lcount;
- Dwarf_Signed i;
- int res;
- Dwarf_Line *linebuf;
-
- res = _dwarf_internal_srclines(die, &linebuf,
- &lcount, /* addrlist= */ true,
- /* linelist= */ false, err);
- if (res != DW_DLV_OK) {
- return res;
+ Dwarf_Small *line_ptr = data_start;
+ Dwarf_Unsigned total_length = 0;
+ int local_length_size = 0;
+ int local_extension_size = 0;
+ Dwarf_Unsigned prologue_length = 0;
+ Dwarf_Half version = 0;
+ Dwarf_Unsigned directories_count = 0;
+ Dwarf_Unsigned directories_malloc = 0;
+ Dwarf_Unsigned files_count = 0;
+ Dwarf_Unsigned files_malloc = 0;
+ Dwarf_Small *line_ptr_end = 0;
+ Dwarf_Small *lp_begin = 0;
+ if(bogus_bytes_ptr) *bogus_bytes_ptr = 0;
+ if(bogus_bytes) *bogus_bytes= 0;
+
+ prefix_out->pf_line_ptr_start = line_ptr;
+ /* READ_AREA_LENGTH updates line_ptr for consumed bytes */
+ READ_AREA_LENGTH(dbg, total_length, Dwarf_Unsigned,
+ line_ptr, local_length_size, local_extension_size);
+
+
+ line_ptr_end = line_ptr + total_length;
+ prefix_out->pf_line_ptr_end = line_ptr_end;
+ prefix_out->pf_length_field_length = local_length_size +
+ local_extension_size;
+ /* ASSERT: prefix_out->pf_length_field_length == line_ptr
+ -prefix_out->pf_line_ptr_start; */
+ if (line_ptr_end > dbg->de_debug_line.dss_data +
+ dbg->de_debug_line.dss_size) {
+ _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+ if (line_ptr_end > data_start + data_length) {
+ _dwarf_error(dbg, err, DW_DLE_DEBUG_LINE_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ }
+ prefix_out->pf_total_length = total_length;
+
+ READ_UNALIGNED(dbg, version, Dwarf_Half,
+ line_ptr, sizeof(Dwarf_Half));
+ prefix_out->pf_version = version;
+ line_ptr += sizeof(Dwarf_Half);
+ if (version != CURRENT_VERSION_STAMP &&
+ version != CURRENT_VERSION_STAMP3) {
+ _dwarf_error(dbg, err, DW_DLE_VERSION_STAMP_ERROR);
+ return (DW_DLV_ERROR);
+ }
+
+ READ_UNALIGNED(dbg, prologue_length, Dwarf_Unsigned,
+ line_ptr, local_length_size);
+ prefix_out->pf_prologue_length = prologue_length;
+ line_ptr += local_length_size;
+ prefix_out->pf_line_prologue_start = line_ptr;
+
+ prefix_out->pf_minimum_instruction_length =
+ *(unsigned char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ prefix_out->pf_default_is_stmt = *(unsigned char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ prefix_out->pf_line_base = *(signed char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Sbyte);
+
+ prefix_out->pf_line_range = *(unsigned char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ prefix_out->pf_opcode_base = *(unsigned char *) line_ptr;
+ line_ptr = line_ptr + sizeof(Dwarf_Small);
+
+ /* Set up the array of standard opcode lengths. */
+ /* We think this works ok even for cross-endian processing of
+ objects. It might be wrong, we might need to specially process
+ the array of ubyte into host order. */
+ prefix_out->pf_opcode_length_table = line_ptr;
+
+ /* pf_opcode_base is one greater than the size of the array. */
+ line_ptr += prefix_out->pf_opcode_base - 1;
+
+ {
+ /* Determine (as best we can) whether the
+ pf_opcode_length_table holds 9 or 12 standard-conforming
+ entries. gcc4 upped to DWARF3's 12 without updating the
+ version number. */
+ int operand_ck_fail = true;
+
+ if (prefix_out->pf_opcode_base >= STANDARD_OPERAND_COUNT_DWARF3) {
+ int mismatch = memcmp(dwarf_standard_opcode_operand_count,
+ prefix_out->pf_opcode_length_table,
+ STANDARD_OPERAND_COUNT_DWARF3);
+ if(mismatch) {
+ if(err_count_out) {
+ print_header_issue(dbg,"standard-operands did not match",
+ data_start,err_count_out);
+ }
+ mismatch = memcmp(dwarf_arm_standard_opcode_operand_count,
+ prefix_out->pf_opcode_length_table,
+ STANDARD_OPERAND_COUNT_DWARF3);
+ if(!mismatch && err_count_out) {
+ print_header_issue(dbg,"arm (incorrect) operands in use",
+ data_start,err_count_out);
+ }
+ }
+ if (!mismatch) {
+ if (version == 2) {
+ if(err_count_out) {
+ print_header_issue(dbg,
+ "standard DWARF3 operands matched, but is DWARF2 linetable",
+ data_start,err_count_out);
+ }
+ }
+ operand_ck_fail = false;
+ prefix_out->pf_std_op_count =
+ STANDARD_OPERAND_COUNT_DWARF3;
+ }
+ }
+ if (operand_ck_fail) {
+ if (prefix_out->pf_opcode_base >=
+ STANDARD_OPERAND_COUNT_DWARF2) {
+
+ int mismatch =
+ memcmp(dwarf_standard_opcode_operand_count,
+ prefix_out->pf_opcode_length_table,
+ STANDARD_OPERAND_COUNT_DWARF2);
+ if(mismatch) {
+ if(err_count_out) {
+ print_header_issue(dbg,"standard-operands-lengths did not match",
+ data_start,err_count_out);
+ }
+ mismatch = memcmp(dwarf_arm_standard_opcode_operand_count,
+ prefix_out->pf_opcode_length_table,
+ STANDARD_OPERAND_COUNT_DWARF2);
+ if(!mismatch && err_count_out) {
+ print_header_issue(dbg,"arm (incorrect) operand in use",
+ data_start,err_count_out);
+ }
+ }
+
+ if (!mismatch) {
+ operand_ck_fail = false;
+ prefix_out->pf_std_op_count =
+ STANDARD_OPERAND_COUNT_DWARF2;
+ }
+ }
+ }
+ if (operand_ck_fail) {
+ /* Here we are not sure what the pf_std_op_count is. */
+ _dwarf_error(dbg, err, DW_DLE_LINE_NUM_OPERANDS_BAD);
+ return (DW_DLV_ERROR);
+ }
}
- laddrs = (Dwarf_Addr *)
- _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount);
- if (laddrs == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
+ /* At this point we no longer need to check operand counts. */
+
+
+ directories_count = 0;
+ directories_malloc = 5;
+ prefix_out->pf_include_directories = malloc(sizeof(Dwarf_Small *) *
+ directories_malloc);
+ if (prefix_out->pf_include_directories == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
}
- loffsets = (Dwarf_Off *)
- _dwarf_get_alloc(dbg, DW_DLA_ADDR, lcount);
- if (loffsets == NULL) {
- _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
- return (DW_DLV_ERROR);
+ memset(prefix_out->pf_include_directories, 0,
+ sizeof(Dwarf_Small *) * directories_malloc);
+
+ while ((*(char *) line_ptr) != '\0') {
+ if (directories_count >= directories_malloc) {
+ Dwarf_Unsigned expand = 2 * directories_malloc;
+ Dwarf_Unsigned bytesalloc = sizeof(Dwarf_Small *) * expand;
+ Dwarf_Small **newdirs =
+ realloc(prefix_out->pf_include_directories,
+ bytesalloc);
+
+ if (!newdirs) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ /* Doubled size, zero out second half. */
+ memset(newdirs + directories_malloc, 0,
+ sizeof(Dwarf_Small *) * directories_malloc);
+ directories_malloc = expand;
+ prefix_out->pf_include_directories = newdirs;
+ }
+ prefix_out->pf_include_directories[directories_count] =
+ line_ptr;
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+ directories_count++;
}
+ prefix_out->pf_include_directories_count = directories_count;
+ line_ptr++;
- for (i = 0; i < lcount; i++) {
- laddrs[i] = linebuf[i]->li_address;
- loffsets[i] = linebuf[i]->li_addr_line.li_offset;
- dwarf_dealloc(dbg, linebuf[i], DW_DLA_LINE);
+ files_count = 0;
+ files_malloc = 5;
+ prefix_out->pf_line_table_file_entries =
+ malloc(sizeof(struct Line_Table_File_Entry_s) * files_malloc);
+ if (prefix_out->pf_line_table_file_entries == NULL) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
}
- dwarf_dealloc(dbg, linebuf, DW_DLA_LIST);
- *returncount = lcount;
- *offs = loffsets;
- *addrs = laddrs;
+ memset(prefix_out->pf_line_table_file_entries, 0,
+ sizeof(struct Line_Table_File_Entry_s) * files_malloc);
+
+ while (*(char *) line_ptr != '\0') {
+ Dwarf_Unsigned utmp;
+ Dwarf_Unsigned dir_index = 0;
+ Dwarf_Unsigned lastmod = 0;
+ Dwarf_Unsigned file_length = 0;
+ struct Line_Table_File_Entry_s *curline;
+ Dwarf_Word leb128_length = 0;
+
+
+ if (files_count >= files_malloc) {
+ Dwarf_Unsigned expand = 2 * files_malloc;
+ struct Line_Table_File_Entry_s *newfiles =
+ realloc(prefix_out->pf_line_table_file_entries,
+ sizeof(struct Line_Table_File_Entry_s) *
+ expand);
+ if (!newfiles) {
+ _dwarf_error(dbg, err, DW_DLE_ALLOC_FAIL);
+ return (DW_DLV_ERROR);
+ }
+ memset(newfiles + files_malloc, 0,
+ sizeof(struct Line_Table_File_Entry_s) *
+ files_malloc);
+ files_malloc = expand;
+ prefix_out->pf_line_table_file_entries = newfiles;
+ }
+ curline = prefix_out->pf_line_table_file_entries + files_count;
+
+ curline->lte_filename = line_ptr;
+ line_ptr = line_ptr + strlen((char *) line_ptr) + 1;
+
+ DECODE_LEB128_UWORD(line_ptr, utmp);
+ dir_index = (Dwarf_Sword) utmp;
+ if (dir_index > directories_count) {
+ _dwarf_error(dbg, err, DW_DLE_DIR_INDEX_BAD);
+ return (DW_DLV_ERROR);
+ }
+ curline->lte_directory_index = dir_index;
+
+ lastmod = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ curline->lte_last_modification_time = lastmod;
+
+ /* Skip over file length. */
+ file_length = _dwarf_decode_u_leb128(line_ptr, &leb128_length);
+ line_ptr = line_ptr + leb128_length;
+ curline->lte_length_of_file = file_length;
+
+ ++files_count;
+
+ }
+ prefix_out->pf_files_count = files_count;
+ /* Skip trailing nul byte */
+ ++line_ptr;
+
+
+ lp_begin = prefix_out->pf_line_prologue_start +
+ prefix_out->pf_prologue_length;
+ if (line_ptr != lp_begin) {
+ if(line_ptr > lp_begin) {
+ _dwarf_error(dbg, err, DW_DLE_LINE_PROLOG_LENGTH_BAD);
+ return (DW_DLV_ERROR);
+ } else {
+ /* Bug in compiler. These
+ * bytes are really part of the instruction
+ * stream. The prefix_out->pf_prologue_length is
+ * wrong (12 too high). */
+ if(bogus_bytes_ptr) {
+ *bogus_bytes_ptr = line_ptr;
+ }
+ if(bogus_bytes) {
+ /* How far off things are. We expect the
+ value 12 ! */
+ *bogus_bytes = (lp_begin - line_ptr);
+ }
+ }
+ /* Ignore the lp_begin calc. Assume line_ptr right.
+ Making up for compiler bug. */
+ lp_begin = line_ptr;
+
+ }
+
+ *updated_data_start_out = lp_begin;
return DW_DLV_OK;
}
+
+
+/* Initialize the Line_Table_Prefix_s struct.
+ memset is not guaranteed a portable initializer, but works
+ fine for current architectures. AFAIK.
+*/
+void
+dwarf_init_line_table_prefix(struct Line_Table_Prefix_s *pf)
+{
+ memset(pf, 0, sizeof(*pf));
+}
+
+/* Free any malloc'd area. of the Line_Table_Prefix_s struct. */
+void
+dwarf_free_line_table_prefix(struct Line_Table_Prefix_s *pf)
+{
+ if (pf->pf_include_directories) {
+ free(pf->pf_include_directories);
+ pf->pf_include_directories = 0;
+ }
+ if (pf->pf_line_table_file_entries) {
+ free(pf->pf_line_table_file_entries);
+ pf->pf_line_table_file_entries = 0;
+ }
+ return;
+}