mirror of
https://github.com/davea42/libdwarf-code.git
synced 2025-10-23 01:37:53 +08:00

* dwarfdump.c: Revised -g so it no longer turns on -i. Revised the meaning of -g to mean use old loclist interfaces (for testing the older interfaces with dwarfdump). * print_die.c(get_small_encoding_integer_and_name): a dwarf_dealloc referenced err whereas *err was correct. Revised loclist output making it look a bit like DWARF5 even for DWARF2,3,4 output. Reads better, I think. * print_locs.c: -l gets a 'no longer supported' message dwarfdump/dwarfdump.1 dwarfdump/dwarfdump.c dwarfdump/print_die.c dwarfdump/print_locs.c * dwarf_alloc.c: Added new checks so user mixing up tied dbg with regular dbg won't lead to crashes when calling dwarf_dealloc or dwarf_finish(). Zeroed out some fields to recognize space deallocated. * dwarf_die_deliv.c: Added support of split dwarf DW_AT_[GNU_]ranges_base * dwarf_form.c: Load string from tieddbg when appropriate. * dwarf_harmless.c: On free() zero out a field to show that was done. * dwarf_loc.c: Correct the handling of split dwarf loclist. * dwarf_opaque.h: Add cc_ranges_base_present for split dwarf. Add _dwarf_get_ranges_base_attr_from_tied() for split dwarf. * dwarf_query.c: Get and remember skeleton compilaton unit DW_AT_[GNU_]ranges_base from tied objects for split dwarf. * dwarf_ranges.c: If a tied object present, look for ranges there, not in split dwarf object. * dwarf_util.c: Housekeeping zeros out fields to ensure not used after dealloc. libdwarf/dwarf_alloc.c libdwarf/dwarf_die_deliv.c libdwarf/dwarf_form.c libdwarf/dwarf_harmless.c libdwarf/dwarf_loc.c libdwarf/dwarf_loc2.c libdwarf/dwarf_opaque.h libdwarf/dwarf_original_elf_init.c libdwarf/dwarf_query.c libdwarf/dwarf_ranges.c libdwarf/dwarf_util.c
229 lines
7.2 KiB
C
229 lines
7.2 KiB
C
/*
|
|
|
|
Copyright (C) 2010-2012 David Anderson. All Rights Reserved.
|
|
Portions Copyright 2012 SN Systems Ltd. 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
|
|
as published by the Free Software Foundation.
|
|
|
|
This program is distributed in the hope that it would be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
Further, this software is distributed without any warranty that it is
|
|
free of the rightful claim of any third person regarding infringement
|
|
or the like. Any license provided herein, whether implied or
|
|
otherwise, applies only to this software file. Patent licenses, if
|
|
any, provided herein do not apply to combinations of this program with
|
|
other software, or any other product whatsoever.
|
|
|
|
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., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
|
|
USA.
|
|
|
|
*/
|
|
|
|
/* This implements _dwarf_insert_harmless_error
|
|
and related helper functions for recording
|
|
compiler errors that need not make the input
|
|
unusable.
|
|
|
|
Applications can use dwarf_get_harmless_error_list to
|
|
find (and possibly print) a warning about such errors.
|
|
|
|
The initial error reported here is
|
|
DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE which was a
|
|
bug in a specific compiler.
|
|
|
|
It is a fixed length circular list to constrain
|
|
the space used for errors.
|
|
|
|
The assumption is that these errors are exceedingly
|
|
rare, and indicate a broken compiler (the one that
|
|
produced the object getting the error(s)).
|
|
|
|
dh_maxcount is recorded internally as 1 greater than
|
|
requested. Hiding the fact we always leave one
|
|
slot unused (at least). So a user request for
|
|
N slots really gives the user N usable slots. */
|
|
|
|
|
|
|
|
#include "config.h"
|
|
#include "dwarf_incl.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include "dwarf_frame.h"
|
|
#include "dwarf_harmless.h"
|
|
|
|
|
|
/* The pointers returned here through errmsg_ptrs_array
|
|
become invalidated by any call to libdwarf. Any call.
|
|
*/
|
|
int dwarf_get_harmless_error_list(Dwarf_Debug dbg,
|
|
unsigned count,
|
|
const char ** errmsg_ptrs_array,
|
|
unsigned * errs_count)
|
|
{
|
|
struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
|
|
if (!dhp->dh_errors) {
|
|
dhp->dh_errs_count = 0;
|
|
return DW_DLV_NO_ENTRY;
|
|
}
|
|
if (dhp->dh_errs_count == 0) {
|
|
return DW_DLV_NO_ENTRY;
|
|
}
|
|
if (errs_count) {
|
|
*errs_count = dhp->dh_errs_count;
|
|
}
|
|
if (count) {
|
|
/* NULL terminate the array of pointers */
|
|
--count;
|
|
errmsg_ptrs_array[count] = 0;
|
|
|
|
if (dhp->dh_next_to_use != dhp->dh_first) {
|
|
unsigned i = 0;
|
|
unsigned cur = dhp->dh_first;
|
|
for (i = 0; cur != dhp->dh_next_to_use; ++i) {
|
|
if (i >= count ) {
|
|
/* All output spaces are used. */
|
|
break;
|
|
}
|
|
errmsg_ptrs_array[i] = dhp->dh_errors[cur];
|
|
cur = (cur +1) % dhp->dh_maxcount;
|
|
}
|
|
errmsg_ptrs_array[i] = 0;
|
|
}
|
|
}
|
|
dhp->dh_next_to_use = 0;
|
|
dhp->dh_first = 0;
|
|
dhp->dh_errs_count = 0;
|
|
return DW_DLV_OK;
|
|
}
|
|
|
|
/* strncpy does not null-terminate, this does it. */
|
|
static void
|
|
safe_strncpy(char *targ, char *src, unsigned spaceavail)
|
|
{
|
|
unsigned goodcount = spaceavail-1;
|
|
if (spaceavail < 1) {
|
|
return; /* impossible */
|
|
}
|
|
strncpy(targ,src,goodcount);
|
|
targ[goodcount] = 0;
|
|
}
|
|
|
|
/* Insertion made public is only for testing the harmless error code,
|
|
it is not necessarily useful for libdwarf client code aside
|
|
from code testing libdwarf. */
|
|
void dwarf_insert_harmless_error(Dwarf_Debug dbg,
|
|
char *newerror)
|
|
{
|
|
struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
|
|
unsigned next = 0;
|
|
unsigned cur = dhp->dh_next_to_use;
|
|
char *msgspace;
|
|
if (!dhp->dh_errors) {
|
|
dhp->dh_errs_count++;
|
|
return;
|
|
}
|
|
msgspace = dhp->dh_errors[cur];
|
|
safe_strncpy(msgspace, newerror,DW_HARMLESS_ERROR_MSG_STRING_SIZE);
|
|
next = (cur+1) % dhp->dh_maxcount;
|
|
dhp->dh_errs_count++;
|
|
dhp->dh_next_to_use = next;
|
|
if (dhp->dh_next_to_use == dhp->dh_first) {
|
|
/* Array is full set full invariant. */
|
|
dhp->dh_first = (dhp->dh_first+1) % dhp->dh_maxcount;
|
|
}
|
|
}
|
|
|
|
/* The size of the circular list of strings may be set
|
|
and reset as desired. Returns the previous size of
|
|
the list. If the list is shortened excess error entries
|
|
are simply dropped.
|
|
If the reallocation fails the list size is left unchanged.
|
|
Do not make this a long list!
|
|
|
|
Remember the maxcount we record is 1 > the user count,
|
|
so we adjust it so it looks like the user count.
|
|
*/
|
|
unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug dbg,
|
|
unsigned maxcount )
|
|
{
|
|
struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
|
|
unsigned prevcount = dhp->dh_maxcount;
|
|
if (maxcount != 0) {
|
|
++maxcount;
|
|
if (maxcount != dhp->dh_maxcount) {
|
|
/* Assign transfers 'ownership' of the malloc areas
|
|
to oldarray. */
|
|
struct Dwarf_Harmless_s oldarray = *dhp;
|
|
/* Do not double increment the max, the init() func
|
|
increments it too. */
|
|
dwarf_harmless_init(dhp,maxcount-1);
|
|
if (oldarray.dh_next_to_use != oldarray.dh_first) {
|
|
unsigned i = 0;
|
|
for (i = oldarray.dh_first; i != oldarray.dh_next_to_use;
|
|
i = (i+1)%oldarray.dh_maxcount) {
|
|
dwarf_insert_harmless_error(dbg,oldarray.dh_errors[i]);
|
|
}
|
|
if (oldarray.dh_errs_count > dhp->dh_errs_count) {
|
|
dhp->dh_errs_count = oldarray.dh_errs_count;
|
|
}
|
|
}
|
|
dwarf_harmless_cleanout(&oldarray);
|
|
}
|
|
}
|
|
return prevcount-1;
|
|
}
|
|
|
|
/* Only callable from within libdwarf (as a practical matter)
|
|
*/
|
|
void
|
|
dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size)
|
|
{
|
|
unsigned i = 0;
|
|
memset(dhp,0,sizeof(*dhp));
|
|
dhp->dh_maxcount = size +1;
|
|
dhp->dh_errors = (char **)malloc(sizeof( char *) *dhp->dh_maxcount);
|
|
if (!dhp->dh_errors) {
|
|
dhp->dh_maxcount = 0;
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < dhp->dh_maxcount; ++i) {
|
|
char *newstr =
|
|
(char *)malloc(DW_HARMLESS_ERROR_MSG_STRING_SIZE);
|
|
dhp->dh_errors[i] = newstr;
|
|
if (!newstr) {
|
|
dhp->dh_maxcount = 0;
|
|
/* Let it leak, the leak is a constrained amount. */
|
|
dhp->dh_errors = 0;
|
|
return;
|
|
}
|
|
/* We make the string content well-defined by an initial
|
|
NUL byte, but this is not really necessary. */
|
|
newstr[0] = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp)
|
|
{
|
|
unsigned i = 0;
|
|
if (!dhp->dh_errors) {
|
|
return;
|
|
}
|
|
for (i = 0; i < dhp->dh_maxcount; ++i) {
|
|
free(dhp->dh_errors[i]);
|
|
dhp->dh_errors[i] = 0;
|
|
}
|
|
free(dhp->dh_errors);
|
|
dhp->dh_errors = 0;
|
|
dhp->dh_maxcount = 0;
|
|
}
|
|
|