📄 obj-elf.c
字号:
static voidadjust_stab_sections (abfd, sec, xxx) bfd *abfd; asection *sec; PTR xxx ATTRIBUTE_UNUSED;{ char *name; asection *strsec; char *p; int strsz, nsyms; if (strncmp (".stab", sec->name, 5)) return; if (!strcmp ("str", sec->name + strlen (sec->name) - 3)) return; name = (char *) alloca (strlen (sec->name) + 4); strcpy (name, sec->name); strcat (name, "str"); strsec = bfd_get_section_by_name (abfd, name); if (strsec) strsz = bfd_section_size (abfd, strsec); else strsz = 0; nsyms = bfd_section_size (abfd, sec) / 12 - 1; p = seg_info (sec)->stabu.p; assert (p != 0); bfd_h_put_16 (abfd, (bfd_vma) nsyms, (bfd_byte *) p + 6); bfd_h_put_32 (abfd, (bfd_vma) strsz, (bfd_byte *) p + 8);}#ifdef NEED_ECOFF_DEBUG/* This function is called by the ECOFF code. It is supposed to record the external symbol information so that the backend can write it out correctly. The ELF backend doesn't actually handle this at the moment, so we do it ourselves. We save the information in the symbol. */voidelf_ecoff_set_ext (sym, ext) symbolS *sym; struct ecoff_extr *ext;{ symbol_get_bfdsym (sym)->udata.p = (PTR) ext;}/* This function is called by bfd_ecoff_debug_externals. It is supposed to *EXT to the external symbol information, and return whether the symbol should be used at all. */static booleanelf_get_extr (sym, ext) asymbol *sym; EXTR *ext;{ if (sym->udata.p == NULL) return false; *ext = *(EXTR *) sym->udata.p; return true;}/* This function is called by bfd_ecoff_debug_externals. It has nothing to do for ELF. *//*ARGSUSED*/static voidelf_set_index (sym, indx) asymbol *sym ATTRIBUTE_UNUSED; bfd_size_type indx ATTRIBUTE_UNUSED;{}#endif /* NEED_ECOFF_DEBUG */voidelf_frob_symbol (symp, puntp) symbolS *symp; int *puntp;{ struct elf_obj_sy *sy_obj;#ifdef NEED_ECOFF_DEBUG if (ECOFF_DEBUGGING) ecoff_frob_symbol (symp);#endif sy_obj = symbol_get_obj (symp); if (sy_obj->size != NULL) { switch (sy_obj->size->X_op) { case O_subtract: S_SET_SIZE (symp, (S_GET_VALUE (sy_obj->size->X_add_symbol) + sy_obj->size->X_add_number - S_GET_VALUE (sy_obj->size->X_op_symbol))); break; case O_constant: S_SET_SIZE (symp, (S_GET_VALUE (sy_obj->size->X_add_symbol) + sy_obj->size->X_add_number)); break; default: as_bad (_(".size expression too complicated to fix up")); break; } free (sy_obj->size); sy_obj->size = NULL; } if (sy_obj->versioned_name != NULL) { char *p; p = strchr (sy_obj->versioned_name, ELF_VER_CHR); know (p != NULL); /* This symbol was given a new name with the .symver directive. If this is an external reference, just rename the symbol to include the version string. This will make the relocs be against the correct versioned symbol. If this is a definition, add an alias. FIXME: Using an alias will permit the debugging information to refer to the right symbol. However, it's not clear whether it is the best approach. */ if (! S_IS_DEFINED (symp)) { /* Verify that the name isn't using the @@ syntax--this is reserved for definitions of the default version to link against. */ if (p[1] == ELF_VER_CHR) { as_bad (_("invalid attempt to declare external version name as default in symbol `%s'"), sy_obj->versioned_name); *puntp = true; } S_SET_NAME (symp, sy_obj->versioned_name); } else { if (p [1] == ELF_VER_CHR && p [2] == ELF_VER_CHR) { size_t l; /* The @@@ syntax is a special case. It renames the symbol name to versioned_name with one `@' removed. */ l = strlen (&p[3]) + 1; memmove (&p [2], &p[3], l); S_SET_NAME (symp, sy_obj->versioned_name); } else { symbolS *symp2; /* FIXME: Creating a new symbol here is risky. We're in the final loop over the symbol table. We can get away with it only because the symbol goes to the end of the list, where the loop will still see it. It would probably be better to do this in obj_frob_file_before_adjust. */ symp2 = symbol_find_or_make (sy_obj->versioned_name); /* Now we act as though we saw symp2 = sym. */ S_SET_SEGMENT (symp2, S_GET_SEGMENT (symp)); /* Subtracting out the frag address here is a hack because we are in the middle of the final loop. */ S_SET_VALUE (symp2, (S_GET_VALUE (symp) - symbol_get_frag (symp)->fr_address)); symbol_set_frag (symp2, symbol_get_frag (symp)); /* This will copy over the size information. */ copy_symbol_attributes (symp2, symp); if (S_IS_WEAK (symp)) S_SET_WEAK (symp2); if (S_IS_EXTERNAL (symp)) S_SET_EXTERNAL (symp2); } } } /* Double check weak symbols. */ if (S_IS_WEAK (symp)) { if (S_IS_COMMON (symp)) as_bad (_("Symbol `%s' can not be both weak and common"), S_GET_NAME (symp)); }#ifdef TC_MIPS /* The Irix 5 and 6 assemblers set the type of any common symbol and any undefined non-function symbol to STT_OBJECT. We try to be compatible, since newer Irix 5 and 6 linkers care. However, we only set undefined symbols to be STT_OBJECT if we are on Irix, because that is the only time gcc will generate the necessary .global directives to mark functions. */ if (S_IS_COMMON (symp)) symbol_get_bfdsym (symp)->flags |= BSF_OBJECT; if (strstr (TARGET_OS, "irix") != NULL && ! S_IS_DEFINED (symp) && (symbol_get_bfdsym (symp)->flags & BSF_FUNCTION) == 0) symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;#endif#if 0 /* TC_PPC */ /* If TC_PPC is defined, we used to force the type of a symbol to be BSF_OBJECT if it was otherwise unset. This was required by some version of VxWorks. Thomas de Lellis <tdel@windriver.com> says that this is no longer needed, so it is now commented out. */ if ((symbol_get_bfdsym (symp)->flags & (BSF_FUNCTION | BSF_FILE | BSF_SECTION_SYM)) == 0 && S_IS_DEFINED (symp)) symbol_get_bfdsym (symp)->flags |= BSF_OBJECT;#endif}voidelf_frob_file (){ bfd_map_over_sections (stdoutput, adjust_stab_sections, (PTR) 0);#ifdef elf_tc_final_processing elf_tc_final_processing ();#endif}/* It removes any unneeded versioned symbols from the symbol table. */voidelf_frob_file_before_adjust (){ if (symbol_rootP) { symbolS *symp; for (symp = symbol_rootP; symp; symp = symbol_next (symp)) if (symbol_get_obj (symp)->versioned_name) { if (!S_IS_DEFINED (symp)) { char *p; /* The @@@ syntax is a special case. If the symbol is not defined, 2 `@'s will be removed from the versioned_name. */ p = strchr (symbol_get_obj (symp)->versioned_name, ELF_VER_CHR); know (p != NULL); if (p [1] == ELF_VER_CHR && p [2] == ELF_VER_CHR) { size_t l = strlen (&p[3]) + 1; memmove (&p [1], &p[3], l); } if (symbol_used_p (symp) == 0 && symbol_used_in_reloc_p (symp) == 0) symbol_remove (symp, &symbol_rootP, &symbol_lastP); } } }}/* It is required that we let write_relocs have the opportunity to optimize away fixups before output has begun, since it is possible to eliminate all fixups for a section and thus we never should have generated the relocation section. */voidelf_frob_file_after_relocs (){#ifdef NEED_ECOFF_DEBUG if (ECOFF_DEBUGGING) /* Generate the ECOFF debugging information. */ { const struct ecoff_debug_swap *debug_swap; struct ecoff_debug_info debug; char *buf; asection *sec; debug_swap = get_elf_backend_data (stdoutput)->elf_backend_ecoff_debug_swap; know (debug_swap != (const struct ecoff_debug_swap *) NULL); ecoff_build_debug (&debug.symbolic_header, &buf, debug_swap); /* Set up the pointers in debug. */#define SET(ptr, offset, type) \ debug.ptr = (type) (buf + debug.symbolic_header.offset) SET (line, cbLineOffset, unsigned char *); SET (external_dnr, cbDnOffset, PTR); SET (external_pdr, cbPdOffset, PTR); SET (external_sym, cbSymOffset, PTR); SET (external_opt, cbOptOffset, PTR); SET (external_aux, cbAuxOffset, union aux_ext *); SET (ss, cbSsOffset, char *); SET (external_fdr, cbFdOffset, PTR); SET (external_rfd, cbRfdOffset, PTR); /* ssext and external_ext are set up just below. */#undef SET /* Set up the external symbols. */ debug.ssext = debug.ssext_end = NULL; debug.external_ext = debug.external_ext_end = NULL; if (! bfd_ecoff_debug_externals (stdoutput, &debug, debug_swap, true, elf_get_extr, elf_set_index)) as_fatal (_("Failed to set up debugging information: %s"), bfd_errmsg (bfd_get_error ())); sec = bfd_get_section_by_name (stdoutput, ".mdebug"); assert (sec != NULL); know (stdoutput->output_has_begun == false); /* We set the size of the section, call bfd_set_section_contents to force the ELF backend to allocate a file position, and then write out the data. FIXME: Is this really the best way to do this? */ sec->_raw_size = bfd_ecoff_debug_size (stdoutput, &debug, debug_swap); /* Pass BUF to bfd_set_section_contents because this will eventually become a call to fwrite, and ISO C prohibits passing a NULL pointer to a stdio function even if the pointer will not be used. */ if (! bfd_set_section_contents (stdoutput, sec, (PTR) buf, (file_ptr) 0, (bfd_size_type) 0)) as_fatal (_("Can't start writing .mdebug section: %s"), bfd_errmsg (bfd_get_error ())); know (stdoutput->output_has_begun == true); know (sec->filepos != 0); if (! bfd_ecoff_write_debug (stdoutput, &debug, debug_swap, sec->filepos)) as_fatal (_("Could not write .mdebug section: %s"), bfd_errmsg (bfd_get_error ())); }#endif /* NEED_ECOFF_DEBUG */}#ifdef SCO_ELF/* Heavily plagarized from obj_elf_version. The idea is to emit the SCO specific identifier in the .notes section to satisfy the SCO linker. This looks more complicated than it really is. As opposed to the "obvious" solution, this should handle the cross dev cases correctly. (i.e, hosting on a 64 bit big endian processor, but generating SCO Elf code) Efficiency isn't a concern, as there should be exactly one of these sections per object module. SCO OpenServer 5 identifies it's ELF modules with a standard ELF .note section. int_32 namesz = 4 ; Name size int_32 descsz = 12 ; Descriptive information int_32 type = 1 ; char name[4] = "SCO" ; Originator name ALWAYS SCO + NULL int_32 version = (major ver # << 16) | version of tools ; int_32 source = (tool_id << 16 ) | 1 ; int_32 info = 0 ; These are set by the SCO tools, but we don't know enough about the source environment to set them. SCO ld currently ignores them, and recommends we set them to zero. */#define SCO_MAJOR_VERSION 0x1#define SCO_MINOR_VERSION 0x1voidsco_id (){ char *name; unsigned int c; char ch; char *p; asection *seg = now_seg; subsegT subseg = now_subseg; Elf_Internal_Note i_note; Elf_External_Note e_note; asection *note_secp = (asection *) NULL; int i, len; /* create the .note section */ note_secp = subseg_new (".note", 0); bfd_set_section_flags (stdoutput, note_secp, SEC_HAS_CONTENTS | SEC_READONLY); /* process the version string */ i_note.namesz = 4; i_note.descsz = 12; /* 12 descriptive bytes */ i_note.type = NT_VERSION; /* Contains a version string */ p = frag_more (sizeof (i_note.namesz)); md_number_to_chars (p, (valueT) i_note.namesz, 4); p = frag_more (sizeof (i_note.descsz)); md_number_to_chars (p, (valueT) i_note.descsz, 4); p = frag_more (sizeof (i_note.type)); md_number_to_chars (p, (valueT) i_note.type, 4); p = frag_more (4); strcpy (p, "SCO"); /* Note: this is the version number of the ELF we're representing */ p = frag_more (4); md_number_to_chars (p, (SCO_MAJOR_VERSION << 16) | (SCO_MINOR_VERSION), 4); /* Here, we pick a magic number for ourselves (yes, I "registered" it with SCO. The bottom bit shows that we are compat with the SCO ABI. */ p = frag_more (4); md_number_to_chars (p, 0x4c520000 | 0x0001, 4); /* If we knew (or cared) what the source language options were, we'd fill them in here. SCO has given us permission to ignore these and just set them to zero. */ p = frag_more (4); md_number_to_chars (p, 0x0000, 4); frag_align (2, 0, 0); /* We probably can't restore the current segment, for there likely isn't one yet... */ if (seg && subseg) subseg_set (seg, subseg);}#endif /* SCO_ELF */static intelf_separate_stab_sections (){#ifdef NEED_ECOFF_DEBUG return (!ECOFF_DEBUGGING);#else return 1;#endif}static voidelf_init_stab_section (seg) segT seg;{#ifdef NEED_ECOFF_DEBUG if (!ECOFF_DEBUGGING)#endif obj_elf_init_stab_section (seg);}const struct format_ops elf_format_ops ={ bfd_target_elf_flavour, 0, /* dfl_leading_underscore */ 1, /* emit_section_symbols */ elf_begin, elf_file_symbol, elf_frob_symbol, elf_frob_file, elf_frob_file_before_adjust, elf_frob_file_after_relocs, elf_s_get_size, elf_s_set_size, elf_s_get_align, elf_s_set_align, elf_s_get_other, elf_s_set_other, 0, /* s_get_desc */ 0, /* s_set_desc */ 0, /* s_get_type */ 0, /* s_set_type */ elf_copy_symbol_attributes,#ifdef NEED_ECOFF_DEBUG ecoff_generate_asm_lineno, ecoff_stab,#else 0, /* generate_asm_lineno */ 0, /* process_stab */#endif elf_separate_stab_sections, elf_init_stab_section, elf_sec_sym_ok_for_reloc, elf_pop_insert,#ifdef NEED_ECOFF_DEBUG elf_ecoff_set_ext,#else 0, /* ecoff_set_ext */#endif elf_obj_read_begin_hook, elf_obj_symbol_new_hook};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -