1*f3e7f55eSRobert Mustacchi /*
2*f3e7f55eSRobert Mustacchi
3*f3e7f55eSRobert Mustacchi Copyright (C) 2010 David Anderson. All Rights Reserved.
4*f3e7f55eSRobert Mustacchi
5*f3e7f55eSRobert Mustacchi This program is free software; you can redistribute it and/or modify it
6*f3e7f55eSRobert Mustacchi under the terms of version 2.1 of the GNU Lesser General Public License
7*f3e7f55eSRobert Mustacchi as published by the Free Software Foundation.
8*f3e7f55eSRobert Mustacchi
9*f3e7f55eSRobert Mustacchi This program is distributed in the hope that it would be useful, but
10*f3e7f55eSRobert Mustacchi WITHOUT ANY WARRANTY; without even the implied warranty of
11*f3e7f55eSRobert Mustacchi MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12*f3e7f55eSRobert Mustacchi
13*f3e7f55eSRobert Mustacchi Further, this software is distributed without any warranty that it is
14*f3e7f55eSRobert Mustacchi free of the rightful claim of any third person regarding infringement
15*f3e7f55eSRobert Mustacchi or the like. Any license provided herein, whether implied or
16*f3e7f55eSRobert Mustacchi otherwise, applies only to this software file. Patent licenses, if
17*f3e7f55eSRobert Mustacchi any, provided herein do not apply to combinations of this program with
18*f3e7f55eSRobert Mustacchi other software, or any other product whatsoever.
19*f3e7f55eSRobert Mustacchi
20*f3e7f55eSRobert Mustacchi You should have received a copy of the GNU Lesser General Public
21*f3e7f55eSRobert Mustacchi License along with this program; if not, write the Free Software
22*f3e7f55eSRobert Mustacchi Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23*f3e7f55eSRobert Mustacchi USA.
24*f3e7f55eSRobert Mustacchi
25*f3e7f55eSRobert Mustacchi */
26*f3e7f55eSRobert Mustacchi
27*f3e7f55eSRobert Mustacchi /*
28*f3e7f55eSRobert Mustacchi This implements _dwarf_insert_harmless_error
29*f3e7f55eSRobert Mustacchi and related helper functions for recording
30*f3e7f55eSRobert Mustacchi compiler errors that need not make the input
31*f3e7f55eSRobert Mustacchi unusable.
32*f3e7f55eSRobert Mustacchi
33*f3e7f55eSRobert Mustacchi Applications can use dwarf_get_harmless_error_list to
34*f3e7f55eSRobert Mustacchi find (and possibly print) a warning about such errors.
35*f3e7f55eSRobert Mustacchi
36*f3e7f55eSRobert Mustacchi The initial error reported here is
37*f3e7f55eSRobert Mustacchi DW_DLE_DEBUG_FRAME_LENGTH_NOT_MULTIPLE which was a
38*f3e7f55eSRobert Mustacchi bug in a specific compiler.
39*f3e7f55eSRobert Mustacchi
40*f3e7f55eSRobert Mustacchi It is a fixed length circular list to constrain
41*f3e7f55eSRobert Mustacchi the space used for errors.
42*f3e7f55eSRobert Mustacchi
43*f3e7f55eSRobert Mustacchi The assumption is that these errors are exceedingly
44*f3e7f55eSRobert Mustacchi rare, and indicate a broken compiler (the one that
45*f3e7f55eSRobert Mustacchi produced the object getting the error(s)).
46*f3e7f55eSRobert Mustacchi
47*f3e7f55eSRobert Mustacchi dh_maxcount is recorded internally as 1 greater than
48*f3e7f55eSRobert Mustacchi requested. Hiding the fact we always leave one
49*f3e7f55eSRobert Mustacchi slot unused (at least). So a user request for
50*f3e7f55eSRobert Mustacchi N slots really gives the user N usable slots.
51*f3e7f55eSRobert Mustacchi */
52*f3e7f55eSRobert Mustacchi
53*f3e7f55eSRobert Mustacchi
54*f3e7f55eSRobert Mustacchi
55*f3e7f55eSRobert Mustacchi #include "config.h"
56*f3e7f55eSRobert Mustacchi #include "dwarf_incl.h"
57*f3e7f55eSRobert Mustacchi #include <stdio.h>
58*f3e7f55eSRobert Mustacchi #include <stdlib.h>
59*f3e7f55eSRobert Mustacchi #include "dwarf_frame.h"
60*f3e7f55eSRobert Mustacchi #include "dwarf_harmless.h"
61*f3e7f55eSRobert Mustacchi
62*f3e7f55eSRobert Mustacchi
63*f3e7f55eSRobert Mustacchi /* The pointers returned here through errmsg_ptrs_array
64*f3e7f55eSRobert Mustacchi become invalidated by any call to libdwarf. Any call.
65*f3e7f55eSRobert Mustacchi */
dwarf_get_harmless_error_list(Dwarf_Debug dbg,unsigned count,const char ** errmsg_ptrs_array,unsigned * errs_count)66*f3e7f55eSRobert Mustacchi int dwarf_get_harmless_error_list(Dwarf_Debug dbg,
67*f3e7f55eSRobert Mustacchi unsigned count,
68*f3e7f55eSRobert Mustacchi const char ** errmsg_ptrs_array,
69*f3e7f55eSRobert Mustacchi unsigned * errs_count)
70*f3e7f55eSRobert Mustacchi {
71*f3e7f55eSRobert Mustacchi struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
72*f3e7f55eSRobert Mustacchi if(!dhp->dh_errors) {
73*f3e7f55eSRobert Mustacchi dhp->dh_errs_count = 0;
74*f3e7f55eSRobert Mustacchi return DW_DLV_NO_ENTRY;
75*f3e7f55eSRobert Mustacchi }
76*f3e7f55eSRobert Mustacchi if(dhp->dh_errs_count == 0) {
77*f3e7f55eSRobert Mustacchi return DW_DLV_NO_ENTRY;
78*f3e7f55eSRobert Mustacchi }
79*f3e7f55eSRobert Mustacchi if(errs_count) {
80*f3e7f55eSRobert Mustacchi *errs_count = dhp->dh_errs_count;
81*f3e7f55eSRobert Mustacchi }
82*f3e7f55eSRobert Mustacchi if(count) {
83*f3e7f55eSRobert Mustacchi /* NULL terminate the array of pointers */
84*f3e7f55eSRobert Mustacchi --count;
85*f3e7f55eSRobert Mustacchi errmsg_ptrs_array[count] = 0;
86*f3e7f55eSRobert Mustacchi
87*f3e7f55eSRobert Mustacchi if(dhp->dh_next_to_use != dhp->dh_first) {
88*f3e7f55eSRobert Mustacchi unsigned i = 0;
89*f3e7f55eSRobert Mustacchi unsigned cur = dhp->dh_first;
90*f3e7f55eSRobert Mustacchi for(i = 0; cur != dhp->dh_next_to_use; ++i) {
91*f3e7f55eSRobert Mustacchi if(i >= count ) {
92*f3e7f55eSRobert Mustacchi /* All output spaces are used. */
93*f3e7f55eSRobert Mustacchi break;
94*f3e7f55eSRobert Mustacchi }
95*f3e7f55eSRobert Mustacchi errmsg_ptrs_array[i] = dhp->dh_errors[cur];
96*f3e7f55eSRobert Mustacchi cur = (cur +1) % dhp->dh_maxcount;
97*f3e7f55eSRobert Mustacchi }
98*f3e7f55eSRobert Mustacchi errmsg_ptrs_array[i] = 0;
99*f3e7f55eSRobert Mustacchi }
100*f3e7f55eSRobert Mustacchi }
101*f3e7f55eSRobert Mustacchi dhp->dh_next_to_use = 0;
102*f3e7f55eSRobert Mustacchi dhp->dh_first = 0;
103*f3e7f55eSRobert Mustacchi dhp->dh_errs_count = 0;
104*f3e7f55eSRobert Mustacchi return DW_DLV_OK;
105*f3e7f55eSRobert Mustacchi }
106*f3e7f55eSRobert Mustacchi
107*f3e7f55eSRobert Mustacchi /* strncpy does not null-terminate, this does it. */
108*f3e7f55eSRobert Mustacchi static void
safe_strncpy(char * targ,char * src,unsigned spaceavail)109*f3e7f55eSRobert Mustacchi safe_strncpy(char *targ, char *src, unsigned spaceavail)
110*f3e7f55eSRobert Mustacchi {
111*f3e7f55eSRobert Mustacchi unsigned goodcount = spaceavail-1;
112*f3e7f55eSRobert Mustacchi if(spaceavail < 1) {
113*f3e7f55eSRobert Mustacchi return; /* impossible */
114*f3e7f55eSRobert Mustacchi }
115*f3e7f55eSRobert Mustacchi strncpy(targ,src,goodcount);
116*f3e7f55eSRobert Mustacchi targ[goodcount] = 0;
117*f3e7f55eSRobert Mustacchi }
118*f3e7f55eSRobert Mustacchi
119*f3e7f55eSRobert Mustacchi /* Insertion made public is only for testing the harmless error code,
120*f3e7f55eSRobert Mustacchi it is not necessarily useful for libdwarf client code aside
121*f3e7f55eSRobert Mustacchi from code testing libdwarf. */
dwarf_insert_harmless_error(Dwarf_Debug dbg,char * newerror)122*f3e7f55eSRobert Mustacchi void dwarf_insert_harmless_error(Dwarf_Debug dbg,
123*f3e7f55eSRobert Mustacchi char *newerror)
124*f3e7f55eSRobert Mustacchi {
125*f3e7f55eSRobert Mustacchi struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
126*f3e7f55eSRobert Mustacchi unsigned next = 0;
127*f3e7f55eSRobert Mustacchi unsigned cur = dhp->dh_next_to_use;
128*f3e7f55eSRobert Mustacchi char *msgspace;
129*f3e7f55eSRobert Mustacchi if(!dhp->dh_errors) {
130*f3e7f55eSRobert Mustacchi dhp->dh_errs_count++;
131*f3e7f55eSRobert Mustacchi return;
132*f3e7f55eSRobert Mustacchi }
133*f3e7f55eSRobert Mustacchi msgspace = dhp->dh_errors[cur];
134*f3e7f55eSRobert Mustacchi safe_strncpy(msgspace, newerror,DW_HARMLESS_ERROR_MSG_STRING_SIZE);
135*f3e7f55eSRobert Mustacchi next = (cur+1) % dhp->dh_maxcount;
136*f3e7f55eSRobert Mustacchi dhp->dh_errs_count++;
137*f3e7f55eSRobert Mustacchi dhp->dh_next_to_use = next;
138*f3e7f55eSRobert Mustacchi if (dhp->dh_next_to_use == dhp->dh_first) {
139*f3e7f55eSRobert Mustacchi /* Array is full set full invariant. */
140*f3e7f55eSRobert Mustacchi dhp->dh_first = (dhp->dh_first+1) % dhp->dh_maxcount;
141*f3e7f55eSRobert Mustacchi }
142*f3e7f55eSRobert Mustacchi }
143*f3e7f55eSRobert Mustacchi
144*f3e7f55eSRobert Mustacchi /* The size of the circular list of strings may be set
145*f3e7f55eSRobert Mustacchi and reset as desired. Returns the previous size of
146*f3e7f55eSRobert Mustacchi the list. If the list is shortened excess error entries
147*f3e7f55eSRobert Mustacchi are simply dropped.
148*f3e7f55eSRobert Mustacchi If the reallocation fails the list size is left unchanged.
149*f3e7f55eSRobert Mustacchi Do not make this a long list!
150*f3e7f55eSRobert Mustacchi
151*f3e7f55eSRobert Mustacchi Remember the maxcount we record is 1 > the user count,
152*f3e7f55eSRobert Mustacchi so we adjust it so it looks like the user count.
153*f3e7f55eSRobert Mustacchi */
dwarf_set_harmless_error_list_size(Dwarf_Debug dbg,unsigned maxcount)154*f3e7f55eSRobert Mustacchi unsigned dwarf_set_harmless_error_list_size(Dwarf_Debug dbg,
155*f3e7f55eSRobert Mustacchi unsigned maxcount )
156*f3e7f55eSRobert Mustacchi {
157*f3e7f55eSRobert Mustacchi struct Dwarf_Harmless_s *dhp = &dbg->de_harmless_errors;
158*f3e7f55eSRobert Mustacchi unsigned prevcount = dhp->dh_maxcount;
159*f3e7f55eSRobert Mustacchi if(maxcount != 0) {
160*f3e7f55eSRobert Mustacchi ++maxcount;
161*f3e7f55eSRobert Mustacchi if(maxcount != dhp->dh_maxcount) {
162*f3e7f55eSRobert Mustacchi /* Assign transfers 'ownership' of the malloc areas
163*f3e7f55eSRobert Mustacchi to oldarray. */
164*f3e7f55eSRobert Mustacchi struct Dwarf_Harmless_s oldarray = *dhp;
165*f3e7f55eSRobert Mustacchi /* Do not double increment the max, the init() func
166*f3e7f55eSRobert Mustacchi increments it too. */
167*f3e7f55eSRobert Mustacchi dwarf_harmless_init(dhp,maxcount-1);
168*f3e7f55eSRobert Mustacchi if(oldarray.dh_next_to_use != oldarray.dh_first) {
169*f3e7f55eSRobert Mustacchi unsigned i = 0;
170*f3e7f55eSRobert Mustacchi for(i = oldarray.dh_first; i != oldarray.dh_next_to_use;
171*f3e7f55eSRobert Mustacchi i = (i+1)%oldarray.dh_maxcount) {
172*f3e7f55eSRobert Mustacchi dwarf_insert_harmless_error(dbg,oldarray.dh_errors[i]);
173*f3e7f55eSRobert Mustacchi }
174*f3e7f55eSRobert Mustacchi if( oldarray.dh_errs_count > dhp->dh_errs_count) {
175*f3e7f55eSRobert Mustacchi dhp->dh_errs_count = oldarray.dh_errs_count;
176*f3e7f55eSRobert Mustacchi }
177*f3e7f55eSRobert Mustacchi }
178*f3e7f55eSRobert Mustacchi dwarf_harmless_cleanout(&oldarray);
179*f3e7f55eSRobert Mustacchi }
180*f3e7f55eSRobert Mustacchi }
181*f3e7f55eSRobert Mustacchi return prevcount-1;
182*f3e7f55eSRobert Mustacchi }
183*f3e7f55eSRobert Mustacchi
184*f3e7f55eSRobert Mustacchi void
dwarf_harmless_init(struct Dwarf_Harmless_s * dhp,unsigned size)185*f3e7f55eSRobert Mustacchi dwarf_harmless_init(struct Dwarf_Harmless_s *dhp,unsigned size)
186*f3e7f55eSRobert Mustacchi {
187*f3e7f55eSRobert Mustacchi unsigned i = 0;
188*f3e7f55eSRobert Mustacchi memset(dhp,0,sizeof(*dhp));
189*f3e7f55eSRobert Mustacchi dhp->dh_maxcount = size +1;
190*f3e7f55eSRobert Mustacchi dhp->dh_errors = (char **)malloc(sizeof( char *) *dhp->dh_maxcount);
191*f3e7f55eSRobert Mustacchi if (!dhp->dh_errors) {
192*f3e7f55eSRobert Mustacchi dhp->dh_maxcount = 0;
193*f3e7f55eSRobert Mustacchi return;
194*f3e7f55eSRobert Mustacchi }
195*f3e7f55eSRobert Mustacchi
196*f3e7f55eSRobert Mustacchi for(i = 0; i < dhp->dh_maxcount; ++i) {
197*f3e7f55eSRobert Mustacchi char *newstr =
198*f3e7f55eSRobert Mustacchi (char *)malloc(DW_HARMLESS_ERROR_MSG_STRING_SIZE);
199*f3e7f55eSRobert Mustacchi dhp->dh_errors[i] = newstr;
200*f3e7f55eSRobert Mustacchi if(!newstr) {
201*f3e7f55eSRobert Mustacchi dhp->dh_maxcount = 0;
202*f3e7f55eSRobert Mustacchi /* Let it leak, the leak is a constrained amount. */
203*f3e7f55eSRobert Mustacchi dhp->dh_errors = 0;
204*f3e7f55eSRobert Mustacchi return;
205*f3e7f55eSRobert Mustacchi }
206*f3e7f55eSRobert Mustacchi /* We make the string content well-defined by an initial
207*f3e7f55eSRobert Mustacchi NUL byte, but this is not really necessary. */
208*f3e7f55eSRobert Mustacchi newstr[0] = 0;
209*f3e7f55eSRobert Mustacchi }
210*f3e7f55eSRobert Mustacchi }
211*f3e7f55eSRobert Mustacchi
212*f3e7f55eSRobert Mustacchi void
dwarf_harmless_cleanout(struct Dwarf_Harmless_s * dhp)213*f3e7f55eSRobert Mustacchi dwarf_harmless_cleanout(struct Dwarf_Harmless_s *dhp)
214*f3e7f55eSRobert Mustacchi {
215*f3e7f55eSRobert Mustacchi unsigned i = 0;
216*f3e7f55eSRobert Mustacchi if(!dhp->dh_errors) {
217*f3e7f55eSRobert Mustacchi return;
218*f3e7f55eSRobert Mustacchi }
219*f3e7f55eSRobert Mustacchi for(i = 0; i < dhp->dh_maxcount; ++i) {
220*f3e7f55eSRobert Mustacchi free(dhp->dh_errors[i]);
221*f3e7f55eSRobert Mustacchi }
222*f3e7f55eSRobert Mustacchi free(dhp->dh_errors);
223*f3e7f55eSRobert Mustacchi dhp->dh_errors = 0;
224*f3e7f55eSRobert Mustacchi dhp->dh_maxcount = 0;
225*f3e7f55eSRobert Mustacchi }
226*f3e7f55eSRobert Mustacchi
227