obj-coff.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,530 行 · 第 1/5 页
C
2,530 行
fragS *fragp; bfd_vma size, n_entries, mask; bfd_vma align_power = (bfd_vma)sec->alignment_power + OCTETS_PER_BYTE_POWER; /* The COFF back end in BFD requires that all section sizes be rounded up to multiples of the corresponding section alignments, supposedly because standard COFF has no other way of encoding alignment for sections. If your COFF flavor has a different way of encoding section alignment, then skip this step, as TICOFF does. */ size = bfd_get_section_size_before_reloc (sec); mask = ((bfd_vma) 1 << align_power) - 1;#if !defined(TICOFF) if (size & mask) { bfd_vma new_size; fragS *last; new_size = (size + mask) & ~mask; bfd_set_section_size (stdoutput, sec, new_size); /* If the size had to be rounded up, add some padding in the last non-empty frag. */ fragp = seg_info (sec)->frchainP->frch_root; last = seg_info (sec)->frchainP->frch_last; while (fragp->fr_next != last) fragp = fragp->fr_next; last->fr_address = size; fragp->fr_offset += new_size - size; }#endif /* If the section size is non-zero, the section symbol needs an aux entry associated with it, indicating the size. We don't know all the values yet; coff_frob_symbol will fill them in later. */#ifndef TICOFF if (size != 0 || sec == text_section || sec == data_section || sec == bss_section)#endif { symbolS *secsym = section_symbol (sec); S_SET_STORAGE_CLASS (secsym, C_STAT); S_SET_NUMBER_AUXILIARY (secsym, 1); SF_SET_STATICS (secsym); SA_SET_SCN_SCNLEN (secsym, size); } /* @@ these should be in a "stabs.h" file, or maybe as.h */#ifndef STAB_SECTION_NAME#define STAB_SECTION_NAME ".stab"#endif#ifndef STAB_STRING_SECTION_NAME#define STAB_STRING_SECTION_NAME ".stabstr"#endif if (strcmp (STAB_STRING_SECTION_NAME, sec->name)) return; strsec = sec; sec = subseg_get (STAB_SECTION_NAME, 0); /* size is already rounded up, since other section will be listed first */ size = bfd_get_section_size_before_reloc (strsec); n_entries = bfd_get_section_size_before_reloc (sec) / 12 - 1; /* Find first non-empty frag. It should be large enough. */ fragp = seg_info (sec)->frchainP->frch_root; while (fragp && fragp->fr_fix == 0) fragp = fragp->fr_next; assert (fragp != 0 && fragp->fr_fix >= 12); /* Store the values. */ p = fragp->fr_literal; bfd_h_put_16 (stdoutput, n_entries, (bfd_byte *) p + 6); bfd_h_put_32 (stdoutput, size, (bfd_byte *) p + 8);}voidobj_coff_init_stab_section (seg) segT seg;{ char *file; char *p; char *stabstr_name; unsigned int stroff; /* Make space for this first symbol. */ p = frag_more (12); /* Zero it out. */ memset (p, 0, 12); as_where (&file, (unsigned int *) NULL); stabstr_name = (char *) alloca (strlen (seg->name) + 4); strcpy (stabstr_name, seg->name); strcat (stabstr_name, "str"); stroff = get_stab_string_offset (file, stabstr_name); know (stroff == 1); md_number_to_chars (p, stroff, 4);}#ifdef DEBUG/* for debugging */const char *s_get_name (s) symbolS *s;{ return ((s == NULL) ? "(NULL)" : S_GET_NAME (s));}voidsymbol_dump (){ symbolS *symbolP; for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP)) { printf (_("0x%lx: \"%s\" type = %ld, class = %d, segment = %d\n"), (unsigned long) symbolP, S_GET_NAME(symbolP), (long) S_GET_DATA_TYPE(symbolP), S_GET_STORAGE_CLASS(symbolP), (int) S_GET_SEGMENT(symbolP)); }}#endif /* DEBUG */#else /* not BFD_ASSEMBLER */#include "frags.h"/* This is needed because we include internal bfd things. */#include <time.h>#include "libbfd.h"#include "libcoff.h"#ifdef TE_PE#include "coff/pe.h"#endif/* The NOP_OPCODE is for the alignment fill value. Fill with nop so that we can stick sections together without causing trouble. */#ifndef NOP_OPCODE#define NOP_OPCODE 0x00#endif/* The zeroes if symbol name is longer than 8 chars */#define S_SET_ZEROES(s,v) ((s)->sy_symbol.ost_entry.n_zeroes = (v))#define MIN(a,b) ((a) < (b)? (a) : (b))/* This vector is used to turn a gas internal segment number into a section number suitable for insertion into a coff symbol table. This must correspond to seg_info_off_by_4. */const short seg_N_TYPE[] ={ /* in: segT out: N_TYPE bits */ C_ABS_SECTION, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, C_UNDEF_SECTION, /* SEG_UNKNOWN */ C_UNDEF_SECTION, /* SEG_GOOF */ C_UNDEF_SECTION, /* SEG_EXPR */ C_DEBUG_SECTION, /* SEG_DEBUG */ C_NTV_SECTION, /* SEG_NTV */ C_PTV_SECTION, /* SEG_PTV */ C_REGISTER_SECTION, /* SEG_REGISTER */};int function_lineoff = -1; /* Offset in line#s where the last function started (the odd entry for line #0) *//* structure used to keep the filenames which are too long around so that we can stick them into the string table */struct filename_list{ char *filename; struct filename_list *next;};static struct filename_list *filename_list_head;static struct filename_list *filename_list_tail;static symbolS *last_line_symbol;/* Add 4 to the real value to get the index and compensate the negatives. This vector is used by S_GET_SEGMENT to turn a coff section number into a segment number*/static symbolS *previous_file_symbol;void c_symbol_merge ();static int line_base;symbolS *c_section_symbol ();bfd *abfd;static void fixup_segment PARAMS ((segment_info_type *segP, segT this_segment_type));static void fixup_mdeps PARAMS ((fragS *, object_headers *, segT));static void fill_section PARAMS ((bfd * abfd, object_headers *, unsigned long *));static int c_line_new PARAMS ((symbolS * symbol, long paddr, int line_number, fragS * frag));static void w_symbols PARAMS ((bfd * abfd, char *where, symbolS * symbol_rootP));static void adjust_stab_section PARAMS ((bfd *abfd, segT seg));static void obj_coff_lcomm PARAMS ((int));static void obj_coff_text PARAMS ((int));static void obj_coff_data PARAMS ((int));void obj_coff_section PARAMS ((int));/* When not using BFD_ASSEMBLER, we permit up to 40 sections. This array maps a COFF section number into a gas section number. Because COFF uses negative section numbers, you must add 4 to the COFF section number when indexing into this array; this is done via the SEG_INFO_FROM_SECTION_NUMBER macro. This must correspond to seg_N_TYPE. */static const segT seg_info_off_by_4[] ={ SEG_PTV, SEG_NTV, SEG_DEBUG, SEG_ABSOLUTE, SEG_UNKNOWN, SEG_E0, SEG_E1, SEG_E2, SEG_E3, SEG_E4, SEG_E5, SEG_E6, SEG_E7, SEG_E8, SEG_E9, SEG_E10, SEG_E11, SEG_E12, SEG_E13, SEG_E14, SEG_E15, SEG_E16, SEG_E17, SEG_E18, SEG_E19, SEG_E20, SEG_E21, SEG_E22, SEG_E23, SEG_E24, SEG_E25, SEG_E26, SEG_E27, SEG_E28, SEG_E29, SEG_E30, SEG_E31, SEG_E32, SEG_E33, SEG_E34, SEG_E35, SEG_E36, SEG_E37, SEG_E38, SEG_E39, (segT) 40, (segT) 41, (segT) 42, (segT) 43, (segT) 44, (segT) 45, (segT) 0, (segT) 0, (segT) 0, SEG_REGISTER};#define SEG_INFO_FROM_SECTION_NUMBER(x) (seg_info_off_by_4[(x)+4])static relax_addressTrelax_align (address, alignment) relax_addressT address; long alignment;{ relax_addressT mask; relax_addressT new_address; mask = ~((~0) << alignment); new_address = (address + mask) & (~mask); return (new_address - address);}segTs_get_segment (x) symbolS * x;{ return SEG_INFO_FROM_SECTION_NUMBER (x->sy_symbol.ost_entry.n_scnum);}/* calculate the size of the frag chain and fill in the section header to contain all of it, also fill in the addr of the sections */static unsigned intsize_section (abfd, idx) bfd *abfd ATTRIBUTE_UNUSED; unsigned int idx;{ unsigned int size = 0; fragS *frag = segment_info[idx].frchainP->frch_root; while (frag) { size = frag->fr_address; if (frag->fr_address != size) { fprintf (stderr, _("Out of step\n")); size = frag->fr_address; } switch (frag->fr_type) {#ifdef TC_COFF_SIZEMACHDEP case rs_machine_dependent: size += TC_COFF_SIZEMACHDEP (frag); break;#endif case rs_space: assert (frag->fr_symbol == 0); case rs_fill: case rs_org: size += frag->fr_fix; size += frag->fr_offset * frag->fr_var; break; case rs_align: case rs_align_code: case rs_align_test: { addressT off; size += frag->fr_fix; off = relax_align (size, frag->fr_offset); if (frag->fr_subtype != 0 && off > frag->fr_subtype) off = 0; size += off; } break; default: BAD_CASE (frag->fr_type); break; } frag = frag->fr_next; } segment_info[idx].scnhdr.s_size = size; return size;}static unsigned intcount_entries_in_chain (idx) unsigned int idx;{ unsigned int nrelocs; fixS *fixup_ptr; /* Count the relocations */ fixup_ptr = segment_info[idx].fix_root; nrelocs = 0; while (fixup_ptr != (fixS *) NULL) { if (fixup_ptr->fx_done == 0 && TC_COUNT_RELOC (fixup_ptr)) {#ifdef TC_A29K if (fixup_ptr->fx_r_type == RELOC_CONSTH) nrelocs += 2; else nrelocs++;#else nrelocs++;#endif } fixup_ptr = fixup_ptr->fx_next; } return nrelocs;}#ifdef TE_AUXstatic int compare_external_relocs PARAMS ((const PTR, const PTR));/* AUX's ld expects relocations to be sorted */static intcompare_external_relocs (x, y) const PTR x; const PTR y;{ struct external_reloc *a = (struct external_reloc *) x; struct external_reloc *b = (struct external_reloc *) y; bfd_vma aadr = bfd_getb32 (a->r_vaddr); bfd_vma badr = bfd_getb32 (b->r_vaddr); return (aadr < badr ? -1 : badr < aadr ? 1 : 0);}#endif/* output all the relocations for a section */voiddo_relocs_for (abfd, h, file_cursor) bfd * abfd; object_headers * h; unsigned long *file_cursor;{ unsigned int nrelocs; unsigned int idx; unsigned long reloc_start = *file_cursor; for (idx = SEG_E0; idx < SEG_LAST; idx++) { if (segment_info[idx].scnhdr.s_name[0]) { struct external_reloc *ext_ptr; struct external_reloc *external_reloc_vec; unsigned int external_reloc_size; unsigned int base = segment_info[idx].scnhdr.s_paddr; fixS *fix_ptr = segment_info[idx].fix_root; nrelocs = count_entries_in_chain (idx); if (nrelocs) /* Bypass this stuff if no relocs. This also incidentally avoids a SCO bug, where free(malloc(0)) tends to crash. */ { external_reloc_size = nrelocs * RELSZ; external_reloc_vec = (struct external_reloc *) malloc (external_reloc_size); ext_ptr = external_reloc_vec; /* Fill in the internal coff style reloc struct from the internal fix list. */ while (fix_ptr) { struct internal_reloc intr; /* Only output some of the relocations */ if (fix_ptr->fx_done == 0 && TC_COUNT_RELOC (fix_ptr)) {#ifdef TC_RELOC_MANGLE TC_RELOC_MANGLE (&segment_info[idx], fix_ptr, &intr, base);#else symbolS *dot; symbolS *symbol_ptr = fix_ptr->fx_addsy; intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr); intr.r_vaddr = base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where;#ifdef TC_KEEP_FX_OFFSET intr.r_offset = fix_ptr->fx_offset;#else intr.r_offset = 0;#endif while (symbol_ptr->sy_value.X_op == O_symbol && (! S_IS_DEFINED (symbol_ptr) || S_IS_COMMON (symbol_ptr))) { symbolS *n; /* We must avoid looping, as that can occur with a badly written program. */ n = symbol_ptr->sy_value.X_add_symbol; if (n == symbol_ptr) break; symbol_ptr = n; } /* Turn the segment of the symbol into an offset. */ if (symbol_ptr) { resolve_symbol_value (symbol_ptr, 1); if (! symbol_ptr->sy_resolved) { char *file; unsigned int line; if (expr_symbol_where (symbol_ptr, &file, &line)) as_bad_where (file, line, _("unresolved relocation")); else as_bad (_("bad relocation: symbol `%s' not in symbol table"), S_GET_NAME (symbol_ptr)); } dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot; if (dot) { intr.r_symndx = dot->sy_number; } else { intr.r_symndx = symbol_ptr->sy_number; } } else { intr.r_symndx = -1; }#endif (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr); ext_ptr++;#if defined(TC_A29K) /* The 29k has a special kludge for the high 16 bit reloc. Two relocations are emited, R_IHIHALF, and R_IHCONST. The second one doesn't contain a symbol, but uses the value for offset. */ if (intr.r_type == R_IHIHALF) { /* now emit the second bit */ intr.r_type = R_IHCONST; intr.r_symndx = fix_ptr->fx_addnumber;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?