syms.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 1,302 行 · 第 1/3 页
C
1,302 行
#define STRDXOFF (0)#define TYPEOFF (4)#define OTHEROFF (5)#define DESCOFF (6)#define VALOFF (8)#define STABSIZE (12) info = (struct stab_find_info *) *pinfo; if (info != NULL) { if (info->stabsec == NULL || info->strsec == NULL) { /* No stabs debugging information. */ return true; } stabsize = info->stabsec->_raw_size; strsize = info->strsec->_raw_size; } else { long reloc_size, reloc_count; arelent **reloc_vector; int i; char *name; char *file_name; char *directory_name; char *function_name; info = (struct stab_find_info *) bfd_zalloc (abfd, sizeof *info); if (info == NULL) return false; /* FIXME: When using the linker --split-by-file or --split-by-reloc options, it is possible for the .stab and .stabstr sections to be split. We should handle that. */ info->stabsec = bfd_get_section_by_name (abfd, ".stab"); info->strsec = bfd_get_section_by_name (abfd, ".stabstr"); if (info->stabsec == NULL || info->strsec == NULL) { /* No stabs debugging information. Set *pinfo so that we can return quickly in the info != NULL case above. */ *pinfo = (PTR) info; return true; } stabsize = info->stabsec->_raw_size; strsize = info->strsec->_raw_size; info->stabs = (bfd_byte *) bfd_alloc (abfd, stabsize); info->strs = (bfd_byte *) bfd_alloc (abfd, strsize); if (info->stabs == NULL || info->strs == NULL) return false; if (! bfd_get_section_contents (abfd, info->stabsec, info->stabs, 0, stabsize) || ! bfd_get_section_contents (abfd, info->strsec, info->strs, 0, strsize)) return false; /* If this is a relocateable object file, we have to relocate the entries in .stab. This should always be simple 32 bit relocations against symbols defined in this object file, so this should be no big deal. */ reloc_size = bfd_get_reloc_upper_bound (abfd, info->stabsec); if (reloc_size < 0) return false; reloc_vector = (arelent **) bfd_malloc (reloc_size); if (reloc_vector == NULL && reloc_size != 0) return false; reloc_count = bfd_canonicalize_reloc (abfd, info->stabsec, reloc_vector, symbols); if (reloc_count < 0) { if (reloc_vector != NULL) free (reloc_vector); return false; } if (reloc_count > 0) { arelent **pr; for (pr = reloc_vector; *pr != NULL; pr++) { arelent *r; unsigned long val; asymbol *sym; r = *pr; if (r->howto->rightshift != 0 || r->howto->size != 2 || r->howto->bitsize != 32 || r->howto->pc_relative || r->howto->bitpos != 0 || r->howto->dst_mask != 0xffffffff) { (*_bfd_error_handler) (_("Unsupported .stab relocation")); bfd_set_error (bfd_error_invalid_operation); if (reloc_vector != NULL) free (reloc_vector); return false; } val = bfd_get_32 (abfd, info->stabs + r->address); val &= r->howto->src_mask; sym = *r->sym_ptr_ptr; val += sym->value + sym->section->vma + r->addend; bfd_put_32 (abfd, val, info->stabs + r->address); } } if (reloc_vector != NULL) free (reloc_vector); /* First time through this function, build a table matching function VM addresses to stabs, then sort based on starting VM address. Do this in two passes: once to count how many table entries we'll need, and a second to actually build the table. */ info->indextablesize = 0; saw_fun = 1; for (stab = info->stabs; stab < info->stabs + stabsize; stab += STABSIZE) { if (stab[TYPEOFF] == N_SO) { /* N_SO with null name indicates EOF */ if (bfd_get_32 (abfd, stab + STRDXOFF) == 0) continue; /* if we did not see a function def, leave space for one. */ if (saw_fun == 0) ++info->indextablesize; saw_fun = 0; /* two N_SO's in a row is a filename and directory. Skip */ if (stab + STABSIZE < info->stabs + stabsize && *(stab + STABSIZE + TYPEOFF) == N_SO) { stab += STABSIZE; } } else if (stab[TYPEOFF] == N_FUN) { saw_fun = 1; ++info->indextablesize; } } if (saw_fun == 0) ++info->indextablesize; if (info->indextablesize == 0) return true; ++info->indextablesize; info->indextable = ((struct indexentry *) bfd_alloc (abfd, (sizeof (struct indexentry) * info->indextablesize))); if (info->indextable == NULL) return false; file_name = NULL; directory_name = NULL; saw_fun = 1; for (i = 0, stroff = 0, stab = info->stabs, str = info->strs; i < info->indextablesize && stab < info->stabs + stabsize; stab += STABSIZE) { switch (stab[TYPEOFF]) { case 0: /* This is the first entry in a compilation unit. */ if ((bfd_size_type) ((info->strs + strsize) - str) < stroff) break; str += stroff; stroff = bfd_get_32 (abfd, stab + VALOFF); break; case N_SO: /* The main file name. */ /* The following code creates a new indextable entry with a NULL function name if there were no N_FUNs in a file. Note that a N_SO without a file name is an EOF and there could be 2 N_SO following it with the new filename and directory. */ if (saw_fun == 0) { info->indextable[i].val = bfd_get_32 (abfd, last_stab + VALOFF); info->indextable[i].stab = last_stab; info->indextable[i].str = str; info->indextable[i].directory_name = directory_name; info->indextable[i].file_name = file_name; info->indextable[i].function_name = NULL; ++i; } saw_fun = 0; file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF); if (*file_name == '\0') { directory_name = NULL; file_name = NULL; saw_fun = 1; } else { last_stab = stab; if (stab + STABSIZE >= info->stabs + stabsize || *(stab + STABSIZE + TYPEOFF) != N_SO) { directory_name = NULL; } else { /* Two consecutive N_SOs are a directory and a file name. */ stab += STABSIZE; directory_name = file_name; file_name = ((char *) str + bfd_get_32 (abfd, stab + STRDXOFF)); } } break; case N_SOL: /* The name of an include file. */ file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF); break; case N_FUN: /* A function name. */ saw_fun = 1; name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF); if (*name == '\0') name = NULL; function_name = name; if (name == NULL) continue; info->indextable[i].val = bfd_get_32 (abfd, stab + VALOFF); info->indextable[i].stab = stab; info->indextable[i].str = str; info->indextable[i].directory_name = directory_name; info->indextable[i].file_name = file_name; info->indextable[i].function_name = function_name; ++i; break; } } if (saw_fun == 0) { info->indextable[i].val = bfd_get_32 (abfd, last_stab + VALOFF); info->indextable[i].stab = last_stab; info->indextable[i].str = str; info->indextable[i].directory_name = directory_name; info->indextable[i].file_name = file_name; info->indextable[i].function_name = NULL; ++i; } info->indextable[i].val = (bfd_vma) -1; info->indextable[i].stab = info->stabs + stabsize; info->indextable[i].str = str; info->indextable[i].directory_name = NULL; info->indextable[i].file_name = NULL; info->indextable[i].function_name = NULL; ++i; info->indextablesize = i; qsort (info->indextable, i, sizeof (struct indexentry), cmpindexentry); *pinfo = (PTR) info; } /* We are passed a section relative offset. The offsets in the stabs information are absolute. */ offset += bfd_get_section_vma (abfd, section);#ifdef ENABLE_CACHING if (info->cached_indexentry != NULL && offset >= info->cached_offset && offset < (info->cached_indexentry + 1)->val) { stab = info->cached_stab; indexentry = info->cached_indexentry; file_name = info->cached_file_name; } else#endif { /* Cache non-existant or invalid. Do binary search on indextable. */ long low, high; long mid = -1; indexentry = NULL; low = 0; high = info->indextablesize - 1; while (low != high) { mid = (high + low) / 2; if (offset >= info->indextable[mid].val && offset < info->indextable[mid + 1].val) { indexentry = &info->indextable[mid]; break; } if (info->indextable[mid].val > offset) high = mid; else low = mid + 1; } if (indexentry == NULL) return true; stab = indexentry->stab + STABSIZE; file_name = indexentry->file_name; } directory_name = indexentry->directory_name; str = indexentry->str; for (; stab < (indexentry+1)->stab; stab += STABSIZE) { boolean done; bfd_vma val; done = false; switch (stab[TYPEOFF]) { case N_SOL: /* The name of an include file. */ val = bfd_get_32 (abfd, stab + VALOFF); if (val <= offset) { file_name = (char *) str + bfd_get_32 (abfd, stab + STRDXOFF); *pline = 0; } break; case N_SLINE: case N_DSLINE: case N_BSLINE: /* A line number. The value is relative to the start of the current function. */ val = indexentry->val + bfd_get_32 (abfd, stab + VALOFF); if (val <= offset) { *pline = bfd_get_16 (abfd, stab + DESCOFF);#ifdef ENABLE_CACHING info->cached_stab = stab; info->cached_offset = val; info->cached_file_name = file_name; info->cached_indexentry = indexentry;#endif } if (val > offset) done = true; break; case N_FUN: case N_SO: done = true; break; } if (done) break; } *pfound = true; if (IS_ABSOLUTE_PATH(file_name) || directory_name == NULL) *pfilename = file_name; else { size_t dirlen; dirlen = strlen (directory_name); if (info->filename == NULL || strncmp (info->filename, directory_name, dirlen) != 0 || strcmp (info->filename + dirlen, file_name) != 0) { if (info->filename != NULL) free (info->filename); info->filename = (char *) bfd_malloc (dirlen + strlen (file_name) + 1); if (info->filename == NULL) return false; strcpy (info->filename, directory_name); strcpy (info->filename + dirlen, file_name); } *pfilename = info->filename; } if (indexentry->function_name != NULL) { char *s; /* This will typically be something like main:F(0,1), so we want to clobber the colon. It's OK to change the name, since the string is in our own local storage anyhow. */ s = strchr (indexentry->function_name, ':'); if (s != NULL) *s = '\0'; *pfnname = indexentry->function_name; } return true;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?