From: Tony Reix Date: Wed, 1 Aug 2018 21:55:05 +0000 (+0000) Subject: xcoff.c (struct xcoff_line, [...]): Remove. X-Git-Tag: upstream/12.2.0~29982 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ca9a1314ec5f2b58921e24abdcebae1482c0e2c6;p=platform%2Fupstream%2Fgcc.git xcoff.c (struct xcoff_line, [...]): Remove. * xcoff.c (struct xcoff_line, struct xcoff_line_vector): Remove. (struct xcoff_func, struct xcoff_func_vector): New structs. (xcoff_syminfo): Drop leading dot from symbol name. (xcoff_line_compare, xcoff_line_search): Remove. (xcoff_func_compare, xcoff_func_search): New static functions. (xcoff_lookup_pc): Search function table. (xcoff_add_line, xcoff_process_linenos): Remove. (xcoff_initialize_fileline): Build function table. From-SVN: r263238 --- diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index 0c86e0c..0a117a0 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,14 @@ +2018-08-01 Tony Reix + + * xcoff.c (struct xcoff_line, struct xcoff_line_vector): Remove. + (struct xcoff_func, struct xcoff_func_vector): New structs. + (xcoff_syminfo): Drop leading dot from symbol name. + (xcoff_line_compare, xcoff_line_search): Remove. + (xcoff_func_compare, xcoff_func_search): New static functions. + (xcoff_lookup_pc): Search function table. + (xcoff_add_line, xcoff_process_linenos): Remove. + (xcoff_initialize_fileline): Build function table. + 2018-06-21 Denis Khalikov PR other/86198 diff --git a/libbacktrace/xcoff.c b/libbacktrace/xcoff.c index 1ae001d..84d0340 100644 --- a/libbacktrace/xcoff.c +++ b/libbacktrace/xcoff.c @@ -338,27 +338,32 @@ struct xcoff_incl_vector size_t count; }; -/* Map a single PC value to a file/function/line. */ +/* A growable vector of functions information. */ -struct xcoff_line +struct xcoff_func { /* PC. */ uintptr_t pc; - /* File name. Many entries in the array are expected to point to - the same file name. */ - const char *filename; + /* The size of the function. */ + size_t size; /* Function name. */ - const char *function; - /* Line number. */ - int lineno; + const char *name; + /* File name. */ + const char *filename; + /* Pointer to first lnno entry. */ + uintptr_t lnnoptr; + /* Base address of containing section. */ + uintptr_t sect_base; + /* Starting source line number. */ + int lnno; }; -/* A growable vector of line number information. This is used while - reading the line numbers. */ +/* A growable vector of function information. This is used while + reading the function symbols. */ -struct xcoff_line_vector +struct xcoff_func_vector { - /* Memory. This is an array of struct xcoff_line. */ + /* Memory. This is an array of struct xcoff_func. */ struct backtrace_vector vec; /* Number of valid mappings. */ size_t count; @@ -370,8 +375,16 @@ struct xcoff_fileline_data { /* The data for the next file we know about. */ struct xcoff_fileline_data *next; - /* Line number information. */ - struct xcoff_line_vector vec; + /* Functions information. */ + struct xcoff_func_vector func_vec; + /* Include files information. */ + struct xcoff_incl_vector incl_vec; + /* Line numbers information. */ + const unsigned char *linenos; + size_t linenos_size; + uint64_t lnnoptr0; + /* Loader address. */ + uintptr_t base_address; }; /* An index of DWARF sections we care about. */ @@ -509,6 +522,7 @@ xcoff_syminfo (struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr, { struct xcoff_syminfo_data *edata; struct xcoff_symbol *sym = NULL; + const char *name; if (!state->threaded) { @@ -547,7 +561,13 @@ xcoff_syminfo (struct backtrace_state *state ATTRIBUTE_UNUSED, uintptr_t addr, if (sym == NULL) callback (data, addr, NULL, 0, 0); else - callback (data, addr, sym->name, sym->address, sym->size); + { + name = sym->name; + /* AIX prepends a '.' to function entry points, remove it. */ + if (name && *name == '.') + ++name; + callback (data, addr, name, sym->address, sym->size); + } } /* Return the name of an XCOFF symbol. */ @@ -640,43 +660,76 @@ xcoff_initialize_syminfo (struct backtrace_state *state, return 1; } -/* Compare struct xcoff_line for qsort. */ +/* Compare struct xcoff_func for qsort. */ static int -xcoff_line_compare (const void *v1, const void *v2) +xcoff_func_compare (const void *v1, const void *v2) { - const struct xcoff_line *ln1 = (const struct xcoff_line *) v1; - const struct xcoff_line *ln2 = (const struct xcoff_line *) v2; + const struct xcoff_func *fn1 = (const struct xcoff_func *) v1; + const struct xcoff_func *fn2 = (const struct xcoff_func *) v2; - if (ln1->pc < ln2->pc) + if (fn1->pc < fn2->pc) return -1; - else if (ln1->pc > ln2->pc) + else if (fn1->pc > fn2->pc) return 1; else return 0; } -/* Find a PC in a line vector. We always allocate an extra entry at - the end of the lines vector, so that this routine can safely look - at the next entry. */ +/* Compare a PC against an xcoff_func for bsearch. */ static int -xcoff_line_search (const void *vkey, const void *ventry) +xcoff_func_search (const void *vkey, const void *ventry) { const uintptr_t *key = (const uintptr_t *) vkey; - const struct xcoff_line *entry = (const struct xcoff_line *) ventry; + const struct xcoff_func *entry = (const struct xcoff_func *) ventry; uintptr_t pc; pc = *key; if (pc < entry->pc) return -1; - else if ((entry + 1)->pc == (uintptr_t) -1 || pc >= (entry + 1)->pc) + else if ((entry->size == 0 && pc > entry->pc) + || (entry->size > 0 && pc >= entry->pc + entry->size)) return 1; else return 0; } -/* Look for a PC in the line vector for one module. On success, +/* Compare struct xcoff_incl for qsort. */ + +static int +xcoff_incl_compare (const void *v1, const void *v2) +{ + const struct xcoff_incl *in1 = (const struct xcoff_incl *) v1; + const struct xcoff_incl *in2 = (const struct xcoff_incl *) v2; + + if (in1->begin < in2->begin) + return -1; + else if (in1->begin > in2->begin) + return 1; + else + return 0; +} + +/* Find a lnnoptr in an include file. */ + +static int +xcoff_incl_search (const void *vkey, const void *ventry) +{ + const uintptr_t *key = (const uintptr_t *) vkey; + const struct xcoff_incl *entry = (const struct xcoff_incl *) ventry; + uintptr_t lnno; + + lnno = *key; + if (lnno < entry->begin) + return -1; + else if (lnno > entry->end) + return 1; + else + return 0; +} + +/* Look for a PC in the function vector for one module. On success, call CALLBACK and return whatever it returns. On error, call ERROR_CALLBACK and return 0. Sets *FOUND to 1 if the PC is found, 0 if not. */ @@ -688,26 +741,82 @@ xcoff_lookup_pc (struct backtrace_state *state ATTRIBUTE_UNUSED, backtrace_error_callback error_callback ATTRIBUTE_UNUSED, void *data, int *found) { - const struct xcoff_line *ln; + const struct xcoff_incl *incl, *bincl; + const struct xcoff_func *fn; + const b_xcoff_lineno *lineno; + const unsigned char *lineptr; const char *function; + const char *filename; + uintptr_t lnnoptr, match; + uint32_t lnno = 0; *found = 1; - ln = (struct xcoff_line *) bsearch (&pc, fdata->vec.vec.base, - fdata->vec.count, - sizeof (struct xcoff_line), - xcoff_line_search); - if (ln == NULL) + if ((pc & 3) != 0) + ++pc; + + /* Find the function first. */ + fn = ((struct xcoff_func *) + bsearch (&pc, fdata->func_vec.vec.base, fdata->func_vec.count, + sizeof (struct xcoff_func), xcoff_func_search)); + if (fn == NULL) { *found = 0; return 0; } - function = ln->function; + filename = fn->filename; + + /* Find the line number next. */ + + /* Skip first entry that points to symtab. */ + lnnoptr = fn->lnnoptr + LINESZ; + match = lnnoptr; + + lineptr = fdata->linenos + (lnnoptr - fdata->lnnoptr0); + while (lineptr + LINESZ <= fdata->linenos + fdata->linenos_size) + { + lineno = (const b_xcoff_lineno *) lineptr; + if (lineno->l_lnno == 0) + break; + if (pc <= fdata->base_address + lineno->l_addr.l_paddr - fn->sect_base) + break; + match = lnnoptr; + lnno = lineno->l_lnno; + + lnnoptr += LINESZ; + lineptr += LINESZ; + } + + /* If part of a function other than the beginning comes from an + include file, the line numbers are absolute, rather than + relative to the beginning of the function. */ + incl = ((struct xcoff_incl *) + bsearch (&match, fdata->incl_vec.vec.base, + fdata->incl_vec.count, sizeof (struct xcoff_incl), + xcoff_incl_search)); + if (incl != NULL) + { + bincl = ((struct xcoff_incl *) + bsearch (&fn->lnnoptr, fdata->incl_vec.vec.base, + fdata->incl_vec.count, sizeof (struct xcoff_incl), + xcoff_incl_search)); + if (bincl != NULL && strcmp (incl->filename, bincl->filename) == 0) + { + lnno += fn->lnno - 1; + } + filename = incl->filename; + } + else + { + lnno += fn->lnno - 1; + } + + function = fn->name; /* AIX prepends a '.' to function entry points, remove it. */ - if (*function == '.') + if (function != NULL && *function == '.') ++function; - return callback (data, pc, ln->filename, ln->lineno, function); + return callback (data, pc, filename, lnno, function); } /* Return the file/line information for a PC using the XCOFF lineno @@ -760,146 +869,7 @@ xcoff_fileline (struct backtrace_state *state, uintptr_t pc, return callback (data, pc, NULL, 0, NULL); } -/* Compare struct xcoff_incl for qsort. */ - -static int -xcoff_incl_compare (const void *v1, const void *v2) -{ - const struct xcoff_incl *in1 = (const struct xcoff_incl *) v1; - const struct xcoff_incl *in2 = (const struct xcoff_incl *) v2; - - if (in1->begin < in2->begin) - return -1; - else if (in1->begin > in2->begin) - return 1; - else - return 0; -} - -/* Find a lnnoptr in an include file. */ - -static int -xcoff_incl_search (const void *vkey, const void *ventry) -{ - const uintptr_t *key = (const uintptr_t *) vkey; - const struct xcoff_incl *entry = (const struct xcoff_incl *) ventry; - uintptr_t lnno; - - lnno = *key; - if (lnno < entry->begin) - return -1; - else if (lnno > entry->end) - return 1; - else - return 0; -} - -/* Add a new mapping to the vector of line mappings that we are - building. Returns 1 on success, 0 on failure. */ - -static int -xcoff_add_line (struct backtrace_state *state, uintptr_t pc, - const char *filename, const char *function, uint32_t lnno, - backtrace_error_callback error_callback, void *data, - struct xcoff_line_vector *vec) -{ - struct xcoff_line *ln; - - ln = ((struct xcoff_line *) - backtrace_vector_grow (state, sizeof (struct xcoff_line), - error_callback, data, &vec->vec)); - if (ln == NULL) - return 0; - - ln->pc = pc; - ln->filename = filename; - ln->function = function; - ln->lineno = lnno; - - ++vec->count; - - return 1; -} - -/* Add the line number entries for a function to the line vector. */ - -static int -xcoff_process_linenos (struct backtrace_state *state, uintptr_t base_address, - const b_xcoff_syment *fsym, const char *filename, - const b_xcoff_scnhdr *sects, - const unsigned char *strtab, size_t strtab_size, - uint32_t fcn_lnno, struct xcoff_incl_vector *vec, - struct xcoff_line_vector *lvec, - const unsigned char *linenos, size_t linenos_size, - uintptr_t lnnoptr0, - backtrace_error_callback error_callback, void *data) -{ - const b_xcoff_auxent *aux; - const b_xcoff_lineno *lineno; - const unsigned char *lineptr; - const char *function; - struct xcoff_incl *incl = NULL; - uintptr_t lnnoptr; - uintptr_t pc; - uint32_t lnno; - int begincl; - - aux = (const b_xcoff_auxent *) (fsym + 1); - lnnoptr = aux->x_fcn.x_lnnoptr; - - if (lnnoptr < lnnoptr0 || lnnoptr + LINESZ > lnnoptr0 + linenos_size) - return 0; - - function = xcoff_symname (fsym, strtab, strtab_size); - if (function == NULL) - return 0; - - /* Skip first entry that points to symtab. */ - - lnnoptr += LINESZ; - - lineptr = linenos + (lnnoptr - lnnoptr0); - - begincl = -1; - while (lineptr + LINESZ <= linenos + linenos_size) - { - lineno = (const b_xcoff_lineno *) lineptr; - - lnno = lineno->l_lnno; - if (lnno == 0) - break; - - /* If part of a function other than the beginning comes from an - include file, the line numbers are absolute, rather than - relative to the beginning of the function. */ - incl = (struct xcoff_incl *) bsearch (&lnnoptr, vec->vec.base, - vec->count, - sizeof (struct xcoff_incl), - xcoff_incl_search); - if (begincl == -1) - begincl = incl != NULL; - if (incl != NULL) - { - filename = incl->filename; - if (begincl == 1) - lnno += fcn_lnno - 1; - } - else - lnno += fcn_lnno - 1; - - pc = base_address + lineno->l_addr.l_paddr - - sects[fsym->n_scnum - 1].s_paddr; - xcoff_add_line (state, pc, filename, function, lnno, error_callback, - data, lvec); - - lnnoptr += LINESZ; - lineptr += LINESZ; - } - - return 1; -} - -/* Initialize the line vector info for xcoff_fileline. */ +/* Initialize the function vector info for xcoff_fileline. */ static int xcoff_initialize_fileline (struct backtrace_state *state, @@ -912,15 +882,15 @@ xcoff_initialize_fileline (struct backtrace_state *state, backtrace_error_callback error_callback, void *data) { struct xcoff_fileline_data *fdata; - struct xcoff_incl_vector vec; - struct xcoff_line *ln; + struct xcoff_func *fn; const b_xcoff_syment *fsym; const b_xcoff_auxent *aux; const char *filename; const char *name; struct xcoff_incl *incl; uintptr_t begin, end; - uintptr_t lnno; + uintptr_t lnno, lnnoptr; + uint32_t fsize; size_t i; fdata = ((struct xcoff_fileline_data *) @@ -928,13 +898,17 @@ xcoff_initialize_fileline (struct backtrace_state *state, error_callback, data)); if (fdata == NULL) return 0; - memset (fdata, 0, sizeof *fdata); - memset (&vec, 0, sizeof vec); - - /* Process include files first. */ + fdata->base_address = base_address; + fdata->linenos = linenos; + fdata->linenos_size = linenos_size; + fdata->lnnoptr0 = lnnoptr0; begin = 0; + filename = NULL; + fsym = NULL; + lnnoptr = 0; + fsize = 0; for (i = 0; i < nsyms; ++i) { const b_xcoff_syment *asym = &syms[i]; @@ -951,32 +925,18 @@ xcoff_initialize_fileline (struct backtrace_state *state, end = asym->n_value; incl = ((struct xcoff_incl *) backtrace_vector_grow (state, sizeof (struct xcoff_incl), - error_callback, data, &vec.vec)); + error_callback, data, + &fdata->incl_vec.vec)); if (incl != NULL) { incl->filename = xcoff_symname (asym, strtab, strtab_size); incl->begin = begin; incl->end = end; - ++vec.count; + ++fdata->incl_vec.count; } begin = 0; break; - } - - i += asym->n_numaux; - } - - backtrace_qsort (vec.vec.base, vec.count, - sizeof (struct xcoff_incl), xcoff_incl_compare); - - filename = NULL; - fsym = NULL; - for (i = 0; i < nsyms; ++i) - { - const b_xcoff_syment *asym = &syms[i]; - switch (asym->n_sclass) - { case C_FILE: filename = xcoff_symname (asym, strtab, strtab_size); if (filename == NULL) @@ -988,7 +948,7 @@ xcoff_initialize_fileline (struct backtrace_state *state, file auxiliary entry (by convention) contains the source file name. */ - if (asym->n_numaux > 0 && !strcmp (filename, ".file")) + if (asym->n_numaux > 0 && strcmp (filename, ".file") == 0) { aux = (const b_xcoff_auxent *) (asym + 1); if (aux->x_file._x.x_zeroes != 0) @@ -1010,10 +970,20 @@ xcoff_initialize_fileline (struct backtrace_state *state, case C_HIDEXT: case C_WEAKEXT: fsym = NULL; - if (!ISFCN (asym->n_type) || asym->n_numaux == 0) + lnnoptr = 0; + fsize = 0; + if (!ISFCN (asym->n_type) || asym->n_numaux == 0 + || asym->n_scnum <= 0) break; if (filename == NULL) break; + aux = (const b_xcoff_auxent *) (asym + 1); + lnnoptr = aux->x_fcn.x_lnnoptr; + if (lnnoptr < lnnoptr0 + || lnnoptr + LINESZ > lnnoptr0 + linenos_size) + break; + /* x_fsize will be 0 if there is no debug information. */ + fsize = aux->x_fcn.x_fsize; fsym = asym; break; @@ -1023,8 +993,11 @@ xcoff_initialize_fileline (struct backtrace_state *state, if (fsym == NULL) break; name = xcoff_symname (asym, strtab, strtab_size); - if (name == NULL) - break; + if (name == NULL || strcmp (name, ".bf") != 0) + { + fsym = NULL; + break; + } aux = (const b_xcoff_auxent *) (asym + 1); #if BACKTRACE_XCOFF_SIZE == 32 lnno = (uint32_t) aux->x_block.x_lnnohi << 16 @@ -1032,39 +1005,37 @@ xcoff_initialize_fileline (struct backtrace_state *state, #else lnno = aux->x_block.x_lnno; #endif - if (!strcmp (name, ".bf")) - { - xcoff_process_linenos (state, base_address, fsym, filename, - sects, strtab, strtab_size, lnno, &vec, - &fdata->vec, linenos, linenos_size, - lnnoptr0, error_callback, data); - } - else if (!strcmp (name, ".ef")) - { - fsym = NULL; - } + fn = ((struct xcoff_func *) + backtrace_vector_grow (state, sizeof (struct xcoff_func), + error_callback, data, + &fdata->func_vec.vec)); + if (fn == NULL) + break; + fn->name = xcoff_symname (fsym, strtab, strtab_size); + fn->filename = filename; + fn->sect_base = sects[fsym->n_scnum - 1].s_paddr; + fn->pc = base_address + fsym->n_value - fn->sect_base; + fn->size = fsize; + fn->lnno = lnno; + fn->lnnoptr = lnnoptr; + ++fdata->func_vec.count; break; } i += asym->n_numaux; } - /* Allocate one extra entry at the end. */ - ln = ((struct xcoff_line *) - backtrace_vector_grow (state, sizeof (struct xcoff_line), - error_callback, data, &fdata->vec.vec)); - if (ln == NULL) + if (!backtrace_vector_release (state, &fdata->func_vec.vec, error_callback, + data)) goto fail; - ln->pc = (uintptr_t) -1; - ln->filename = NULL; - ln->function = NULL; - ln->lineno = 0; + backtrace_qsort (fdata->func_vec.vec.base, fdata->func_vec.count, + sizeof (struct xcoff_func), xcoff_func_compare); - if (!backtrace_vector_release (state, &fdata->vec.vec, error_callback, data)) + if (!backtrace_vector_release (state, &fdata->incl_vec.vec, error_callback, + data)) goto fail; - - backtrace_qsort (fdata->vec.vec.base, fdata->vec.count, - sizeof (struct xcoff_line), xcoff_line_compare); + backtrace_qsort (fdata->incl_vec.vec.base, fdata->incl_vec.count, + sizeof (struct xcoff_incl), xcoff_incl_compare); if (!state->threaded) { @@ -1354,6 +1325,7 @@ xcoff_add (struct backtrace_state *state, int descriptor, off_t offset, { size_t linenos_size = (size_t) nlnno * LINESZ; + /* We never release this view. */ if (!backtrace_get_view (state, descriptor, offset + lnnoptr, linenos_size, error_callback, data, &linenos_view)) @@ -1366,9 +1338,6 @@ xcoff_add (struct backtrace_state *state, int descriptor, off_t offset, linenos_view.data, linenos_size, lnnoptr, error_callback, data)) *fileline_fn = xcoff_fileline; - - backtrace_release_view (state, &linenos_view, error_callback, data); - linenos_view_valid = 0; } backtrace_release_view (state, §s_view, error_callback, data);