📄 obj-elf.c
字号:
{ segT new_section; int new_subsection; if (previous_section == 0) { as_bad (_(".previous without corresponding .section; ignored")); return; }#ifdef md_flush_pending_output md_flush_pending_output ();#endif new_section = previous_section; new_subsection = previous_subsection; previous_section = now_seg; previous_subsection = now_subseg; subseg_set (new_section, new_subsection);#ifdef md_elf_section_change_hook md_elf_section_change_hook ();#endif}static voidobj_elf_popsection (xxx) int xxx ATTRIBUTE_UNUSED;{ struct section_stack *top = section_stack; if (top == NULL) { as_bad (_(".popsection without corresponding .pushsection; ignored")); return; }#ifdef md_flush_pending_output md_flush_pending_output ();#endif section_stack = top->next; previous_section = top->prev_seg; previous_subsection = top->prev_subseg; subseg_set (top->seg, top->subseg); free (top);#ifdef md_elf_section_change_hook md_elf_section_change_hook ();#endif}static voidobj_elf_line (ignore) int ignore ATTRIBUTE_UNUSED;{ /* Assume delimiter is part of expression. BSD4.2 as fails with delightful bug, so we are not being incompatible here. */ new_logical_line ((char *) NULL, (int) (get_absolute_expression ())); demand_empty_rest_of_line ();}/* This handles the .symver pseudo-op, which is used to specify a symbol version. The syntax is ``.symver NAME,SYMVERNAME''. SYMVERNAME may contain ELF_VER_CHR ('@') characters. This pseudo-op causes the assembler to emit a symbol named SYMVERNAME with the same value as the symbol NAME. */static voidobj_elf_symver (ignore) int ignore ATTRIBUTE_UNUSED;{ char *name; char c; symbolS *sym; name = input_line_pointer; c = get_symbol_end (); sym = symbol_find_or_make (name); *input_line_pointer = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_bad (_("expected comma after name in .symver")); ignore_rest_of_line (); return; } ++input_line_pointer; name = input_line_pointer; while (1) { c = get_symbol_end (); if (c != ELF_VER_CHR) break; *input_line_pointer++ = c; } if (symbol_get_obj (sym)->versioned_name == NULL) { symbol_get_obj (sym)->versioned_name = xstrdup (name); *input_line_pointer = c; if (strchr (symbol_get_obj (sym)->versioned_name, ELF_VER_CHR) == NULL) { as_bad (_("missing version name in `%s' for symbol `%s'"), symbol_get_obj (sym)->versioned_name, S_GET_NAME (sym)); ignore_rest_of_line (); return; } } else { if (strcmp (symbol_get_obj (sym)->versioned_name, name)) { as_bad (_("multiple versions [`%s'|`%s'] for symbol `%s'"), name, symbol_get_obj (sym)->versioned_name, S_GET_NAME (sym)); ignore_rest_of_line (); return; } *input_line_pointer = c; } demand_empty_rest_of_line ();}/* This handles the .vtable_inherit pseudo-op, which is used to indicate to the linker the hierarchy in which a particular table resides. The syntax is ".vtable_inherit CHILDNAME, PARENTNAME". */struct fix *obj_elf_vtable_inherit (ignore) int ignore ATTRIBUTE_UNUSED;{ char *cname, *pname; symbolS *csym, *psym; char c, bad = 0; if (*input_line_pointer == '#') ++input_line_pointer; cname = input_line_pointer; c = get_symbol_end (); csym = symbol_find (cname); /* GCFIXME: should check that we don't have two .vtable_inherits for the same child symbol. Also, we can currently only do this if the child symbol is already exists and is placed in a fragment. */ if (csym == NULL || symbol_get_frag (csym) == NULL) { as_bad ("expected `%s' to have already been set for .vtable_inherit", cname); bad = 1; } *input_line_pointer = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_bad ("expected comma after name in .vtable_inherit"); ignore_rest_of_line (); return NULL; } ++input_line_pointer; SKIP_WHITESPACE (); if (*input_line_pointer == '#') ++input_line_pointer; if (input_line_pointer[0] == '0' && (input_line_pointer[1] == '\0' || isspace ((unsigned char) input_line_pointer[1]))) { psym = section_symbol (absolute_section); ++input_line_pointer; } else { pname = input_line_pointer; c = get_symbol_end (); psym = symbol_find_or_make (pname); *input_line_pointer = c; } demand_empty_rest_of_line (); if (bad) return NULL; assert (symbol_get_value_expression (csym)->X_op == O_constant); return fix_new (symbol_get_frag (csym), symbol_get_value_expression (csym)->X_add_number, 0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);}/* This handles the .vtable_entry pseudo-op, which is used to indicate to the linker that a vtable slot was used. The syntax is ".vtable_entry tablename, offset". */struct fix *obj_elf_vtable_entry (ignore) int ignore ATTRIBUTE_UNUSED;{ char *name; symbolS *sym; offsetT offset; char c; if (*input_line_pointer == '#') ++input_line_pointer; name = input_line_pointer; c = get_symbol_end (); sym = symbol_find_or_make (name); *input_line_pointer = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_bad ("expected comma after name in .vtable_entry"); ignore_rest_of_line (); return NULL; } ++input_line_pointer; if (*input_line_pointer == '#') ++input_line_pointer; offset = get_absolute_expression (); demand_empty_rest_of_line (); return fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0, BFD_RELOC_VTABLE_ENTRY);}voidelf_obj_read_begin_hook (){#ifdef NEED_ECOFF_DEBUG if (ECOFF_DEBUGGING) ecoff_read_begin_hook ();#endif}voidelf_obj_symbol_new_hook (symbolP) symbolS *symbolP;{ struct elf_obj_sy *sy_obj; sy_obj = symbol_get_obj (symbolP); sy_obj->size = NULL; sy_obj->versioned_name = NULL;#ifdef NEED_ECOFF_DEBUG if (ECOFF_DEBUGGING) ecoff_symbol_new_hook (symbolP);#endif}voidobj_elf_version (ignore) int ignore ATTRIBUTE_UNUSED;{ 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; SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { ++input_line_pointer; /* -> 1st char of string. */ name = input_line_pointer; while (is_a_char (c = next_char_of_string ())) ; c = *input_line_pointer; *input_line_pointer = '\0'; *(input_line_pointer - 1) = '\0'; *input_line_pointer = c; /* 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 */ len = strlen (name); i_note.namesz = ((len + 1) + 3) & ~3; /* round this to word boundary */ i_note.descsz = 0; /* no description */ i_note.type = NT_VERSION; p = frag_more (sizeof (e_note.namesz)); md_number_to_chars (p, (valueT) i_note.namesz, 4); p = frag_more (sizeof (e_note.descsz)); md_number_to_chars (p, (valueT) i_note.descsz, 4); p = frag_more (sizeof (e_note.type)); md_number_to_chars (p, (valueT) i_note.type, 4); for (i = 0; i < len; i++) { ch = *(name + i); { FRAG_APPEND_1_CHAR (ch); } } frag_align (2, 0, 0); subseg_set (seg, subseg); } else { as_bad (_("Expected quoted string")); } demand_empty_rest_of_line ();}static voidobj_elf_size (ignore) int ignore ATTRIBUTE_UNUSED;{ char *name = input_line_pointer; char c = get_symbol_end (); char *p; expressionS exp; symbolS *sym; p = input_line_pointer; *p = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { *p = 0; as_bad (_("expected comma after name `%s' in .size directive"), name); *p = c; ignore_rest_of_line (); return; } input_line_pointer++; expression (&exp); if (exp.X_op == O_absent) { as_bad (_("missing expression in .size directive")); exp.X_op = O_constant; exp.X_add_number = 0; } *p = 0; sym = symbol_find_or_make (name); *p = c; if (exp.X_op == O_constant) S_SET_SIZE (sym, exp.X_add_number); else { symbol_get_obj (sym)->size = (expressionS *) xmalloc (sizeof (expressionS)); *symbol_get_obj (sym)->size = exp; } demand_empty_rest_of_line ();}/* Handle the ELF .type pseudo-op. This sets the type of a symbol. There are five syntaxes: The first (used on Solaris) is .type SYM,#function The second (used on UnixWare) is .type SYM,@function The third (reportedly to be used on Irix 6.0) is .type SYM STT_FUNC The fourth (used on NetBSD/Arm and Linux/ARM) is .type SYM,%function The fifth (used on SVR4/860) is .type SYM,"function" */static voidobj_elf_type (ignore) int ignore ATTRIBUTE_UNUSED;{ char *name; char c; int type; const char *typename; symbolS *sym; elf_symbol_type *elfsym; name = input_line_pointer; c = get_symbol_end (); sym = symbol_find_or_make (name); elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym); *input_line_pointer = c; SKIP_WHITESPACE (); if (*input_line_pointer == ',') ++input_line_pointer; SKIP_WHITESPACE (); if ( *input_line_pointer == '#' || *input_line_pointer == '@' || *input_line_pointer == '"' || *input_line_pointer == '%') ++input_line_pointer; typename = input_line_pointer; c = get_symbol_end (); type = 0; if (strcmp (typename, "function") == 0 || strcmp (typename, "STT_FUNC") == 0) type = BSF_FUNCTION; else if (strcmp (typename, "object") == 0 || strcmp (typename, "STT_OBJECT") == 0) type = BSF_OBJECT;#ifdef md_elf_symbol_type else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1) ;#endif else as_bad (_("ignoring unrecognized symbol type \"%s\""), typename); *input_line_pointer = c; if (*input_line_pointer == '"') ++input_line_pointer; elfsym->symbol.flags |= type; demand_empty_rest_of_line ();}static voidobj_elf_ident (ignore) int ignore ATTRIBUTE_UNUSED;{ static segT comment_section; segT old_section = now_seg; int old_subsection = now_subseg;#ifdef md_flush_pending_output md_flush_pending_output ();#endif if (!comment_section) { char *p; comment_section = subseg_new (".comment", 0); bfd_set_section_flags (stdoutput, comment_section, SEC_READONLY | SEC_HAS_CONTENTS); p = frag_more (1); *p = 0; } else subseg_set (comment_section, 0); stringer (1); subseg_set (old_section, old_subsection);}#ifdef INIT_STAB_SECTION/* The first entry in a .stabs section is special. */voidobj_elf_init_stab_section (seg) segT seg;{ char *file; char *p; char *stabstr_name; unsigned int stroff; /* Force the section to align to a longword boundary. Without this, UnixWare ar crashes. */ bfd_set_section_alignment (stdoutput, seg, 2); /* 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 (segment_name (seg)) + 4); strcpy (stabstr_name, segment_name (seg)); strcat (stabstr_name, "str"); stroff = get_stab_string_offset (file, stabstr_name); know (stroff == 1); md_number_to_chars (p, stroff, 4); seg_info (seg)->stabu.p = p;}#endif/* Fill in the counts in the first entry in a .stabs section. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -