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