void trampoline_target(char * target, char * output) { struct bin_file * bf = load_bin_file(target, output); bf_trampoline_basic_blk(bf, disasm_bin_file_sym(bf, symbol_find(&bf->sym_table, "f1"), TRUE), disasm_bin_file_sym(bf, symbol_find(&bf->sym_table, "f_trampoline"), TRUE)); close_bin_file(bf); }
void s_ifdef (int test_defined) { /* Points to name of symbol. */ char *name; /* Points to symbol. */ symbolS *symbolP; struct conditional_frame cframe; char c; /* Leading whitespace is part of operand. */ SKIP_WHITESPACE (); name = input_line_pointer; if (!is_name_beginner (*name)) { as_bad (_("invalid identifier for \".ifdef\"")); obstack_1grow (&cond_obstack, 0); ignore_rest_of_line (); return; } c = get_symbol_end (); symbolP = symbol_find (name); *input_line_pointer = c; initialize_cframe (&cframe); if (cframe.dead_tree) cframe.ignoring = 1; else { int is_defined; /* Use the same definition of 'defined' as .equiv so that a symbol which has been referenced but not yet given a value/address is considered to be undefined. */ is_defined = symbolP != NULL && S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section; cframe.ignoring = ! (test_defined ^ is_defined); } current_cframe = ((struct conditional_frame *) obstack_copy (&cond_obstack, &cframe, sizeof (cframe))); if (LISTING_SKIP_COND () && cframe.ignoring && (cframe.previous_cframe == NULL || ! cframe.previous_cframe->ignoring)) listing_list (2); demand_empty_rest_of_line (); }
void pecoff_obj_clear_weak_hook (symbolS *symbolP) { symbolS *alternateP; S_SET_STORAGE_CLASS (symbolP, 0); SA_SET_SYM_FSIZE (symbolP, 0); alternateP = symbol_find (weak_name2altname (S_GET_NAME (symbolP))); S_CLEAR_EXTERNAL (alternateP); }
pointer symbol_add(VM, char *str) { pointer obj; int ret; khiter_t iter; obj = symbol_find(vm, str); if (!obj) { obj = symbol_alloc(vm, str); iter = kh_put(STR, vm->symbol_table, AR_STRING(obj).val, &ret); kh_val(vm->symbol_table, iter) = obj; } return obj; }
symbolS * section_symbol (segT sec) { segment_info_type *seginfo = seg_info (sec); symbolS *s; if (seginfo == 0) abort (); if (seginfo->sym) return seginfo->sym; #ifndef EMIT_SECTION_SYMBOLS #define EMIT_SECTION_SYMBOLS 1 #endif if (! EMIT_SECTION_SYMBOLS || symbol_table_frozen) { /* Here we know it won't be going into the symbol table. */ s = symbol_create (sec->symbol->name, sec, 0, &zero_address_frag); } else { segT seg; s = symbol_find (sec->symbol->name); /* We have to make sure it is the right symbol when we have multiple sections with the same section name. */ if (s == NULL || ((seg = S_GET_SEGMENT (s)) != sec && seg != undefined_section)) s = symbol_new (sec->symbol->name, sec, 0, &zero_address_frag); else if (seg == undefined_section) { S_SET_SEGMENT (s, sec); symbol_set_frag (s, &zero_address_frag); } } S_CLEAR_EXTERNAL (s); /* Use the BFD section symbol, if possible. */ if (obj_sec_sym_ok_for_reloc (sec)) symbol_set_bfdsym (s, sec->symbol); else symbol_get_bfdsym (s)->flags |= BSF_SECTION_SYM; seginfo->sym = s; return s; }
/* Returns: * -1 Not enough data available * 0 Constant * 1 Symbol */ int ckrange(int skip, char *str) { int val, off; struct symbol *symb; if(t[skip+0]==-1 || t[skip+1]==-1) { /* not enough data in file */ return -1; } val=t[skip+0]+256*t[skip+1]; if(pass==1 || pass==2 || (!a_labels)) { /* on first two passes don't bother printing labels (or if * labels are disabled) */ sprintf(str,"0%04xh",val); return 0; } /* not in area covered by file being disassembled */ /* NOTE: such symbols should already be * removed by symbol_remove_nonlabels() */ /* if((val<start) || (val>end)) { sprintf(str,"0%04xh",val); return 0; } */ symb=symbol_find(val); if(symb!=NULL) { /* exact match */ sprintf(str,"%s", symb->name); return 1; } symb=symbol_find_range(val); if(symb!=NULL) { f_smc=1; off=val-symb->val; sprintf(str,"%s+%d", symb->name, off); return 1; } /* no label found */ sprintf(str, "0%04xh", val); return 0; }
/* Returns: * -1 Not enough data available * 0 Constant * 1 Symbol */ int ckrange_rel(int skip, int pc, char *str) { int val; struct symbol *symb=NULL; if(t[skip]==-1) return -1; if(a_labels) { if(t[skip]<128) { val=pc+2+t[skip]; } else { val=pc+2+t[skip]-256; } symb=symbol_find(val & 0xffff); } if(a_labels && symb!=NULL) { /* print a label */ sprintf(str, "%s", symb->name); return 1; } else { if(a_zilog) { /* old Zilog za.com */ if(t[1]<128) { sprintf(str,"%d",t[1]+2); } else { sprintf(str,"%d",t[1]+2-256); } } else { /* zasm by Günter Woigk and * z80asm */ if(t[1]<128) { sprintf(str,"$%+d",t[1]+2); } else { sprintf(str,"$%+d",t[1]+2-256); } } return 0; } }
/* * layout_indirect_symbols() setups the indirect symbol tables by looking up or * creating symbol from the indirect symbol names and recording the symbol * pointers. It returns the total count of indirect symbol table entries. */ static uint32_t layout_indirect_symbols(void) { struct frchain *frchainP; uint32_t section_type, total, count, stride; isymbolS *isymbolP; symbolS *symbolP; /* * Mark symbols that only appear in a lazy section with * REFERENCE_FLAG_UNDEFINED_LAZY. To do this we first make sure a * symbol exists for all non-lazy symbols. Then we make a pass looking * up the lazy symbols and if not there we make the symbol and mark it * with REFERENCE_FLAG_UNDEFINED_LAZY. */ for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ section_type = frchainP->frch_section.flags & SECTION_TYPE; if(section_type == S_NON_LAZY_SYMBOL_POINTERS){ for(isymbolP = frchainP->frch_isym_root; isymbolP != NULL; isymbolP = isymbolP->isy_next){ /* (void)symbol_find_or_make(isymbolP->isy_name); */ symbolP = symbol_find(isymbolP->isy_name); if(symbolP == NULL){ symbolP = symbol_new(isymbolP->isy_name, N_UNDF, 0, 0, 0, &zero_address_frag); symbol_table_insert(symbolP); } } } } for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ section_type = frchainP->frch_section.flags & SECTION_TYPE; if(section_type == S_LAZY_SYMBOL_POINTERS || section_type == S_SYMBOL_STUBS){ for(isymbolP = frchainP->frch_isym_root; isymbolP != NULL; isymbolP = isymbolP->isy_next){ symbolP = symbol_find(isymbolP->isy_name); if(symbolP == NULL){ symbolP = symbol_find_or_make(isymbolP->isy_name); symbolP->sy_desc |= REFERENCE_FLAG_UNDEFINED_LAZY; } } } } total = 0; for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){ section_type = frchainP->frch_section.flags & SECTION_TYPE; if(section_type == S_LAZY_SYMBOL_POINTERS || section_type == S_NON_LAZY_SYMBOL_POINTERS || section_type == S_SYMBOL_STUBS){ count = 0; for(isymbolP = frchainP->frch_isym_root; isymbolP != NULL; isymbolP = isymbolP->isy_next){ /* symbolP = symbol_find_or_make(isymbolP->isy_name); */ symbolP = symbol_find(isymbolP->isy_name); if(symbolP == NULL){ symbolP = symbol_new(isymbolP->isy_name, N_UNDF, 0, 0, 0, &zero_address_frag); symbol_table_insert(symbolP); } isymbolP->isy_symbol = symbolP; count++; } /* * Check for missing indirect symbols. */ if(section_type == S_SYMBOL_STUBS) stride = frchainP->frch_section.reserved2; else stride = sizeof(signed_target_addr_t); if(frchainP->frch_section.size / stride != count) as_bad("missing indirect symbols for section (%s,%s)", frchainP->frch_section.segname, frchainP->frch_section.sectname); /* * Set the index into the indirect symbol table for this * section into the reserved1 field. */ frchainP->frch_section.reserved1 = total; total += count; } } return(total); }
static void obj_coff_endef (int ignore ATTRIBUTE_UNUSED) { symbolS *symbolP = NULL; dim_index = 0; if (def_symbol_in_progress == NULL) { as_warn (_(".endef pseudo-op used outside of .def/.endef: ignored.")); demand_empty_rest_of_line (); return; } /* Set the section number according to storage class. */ switch (S_GET_STORAGE_CLASS (def_symbol_in_progress)) { case C_STRTAG: case C_ENTAG: case C_UNTAG: SF_SET_TAG (def_symbol_in_progress); /* Fall through. */ case C_FILE: case C_TPDEF: SF_SET_DEBUG (def_symbol_in_progress); S_SET_SEGMENT (def_symbol_in_progress, fetch_coff_debug_section ()); break; case C_EFCN: SF_SET_LOCAL (def_symbol_in_progress); /* Do not emit this symbol. */ /* Fall through. */ case C_BLOCK: SF_SET_PROCESS (def_symbol_in_progress); /* Will need processing before writing. */ /* Fall through. */ case C_FCN: { const char *name; S_SET_SEGMENT (def_symbol_in_progress, text_section); name = S_GET_NAME (def_symbol_in_progress); if (name[0] == '.' && name[2] == 'f' && name[3] == '\0') { switch (name[1]) { case 'b': /* .bf */ if (! in_function ()) as_warn (_("`%s' symbol without preceding function"), name); /* Will need relocating. */ SF_SET_PROCESS (def_symbol_in_progress); clear_function (); break; #ifdef TE_PE case 'e': /* .ef */ /* The MS compilers output the actual endline, not the function-relative one... we want to match without changing the assembler input. */ SA_SET_SYM_LNNO (def_symbol_in_progress, (SA_GET_SYM_LNNO (def_symbol_in_progress) + coff_line_base)); break; #endif } } } break; #ifdef C_AUTOARG case C_AUTOARG: #endif /* C_AUTOARG */ case C_AUTO: case C_REG: case C_ARG: case C_REGPARM: case C_FIELD: /* According to the COFF documentation: http://osr5doc.sco.com:1996/topics/COFF_SectNumFld.html A special section number (-2) marks symbolic debugging symbols, including structure/union/enumeration tag names, typedefs, and the name of the file. A section number of -1 indicates that the symbol has a value but is not relocatable. Examples of absolute-valued symbols include automatic and register variables, function arguments, and .eos symbols. But from Ian Lance Taylor: http://sources.redhat.com/ml/binutils/2000-08/msg00202.html the actual tools all marked them as section -1. So the GNU COFF assembler follows historical COFF assemblers. However, it causes problems for djgpp http://sources.redhat.com/ml/binutils/2000-08/msg00210.html By defining STRICTCOFF, a COFF port can make the assembler to follow the documented behavior. */ #ifdef STRICTCOFF case C_MOS: case C_MOE: case C_MOU: case C_EOS: #endif SF_SET_DEBUG (def_symbol_in_progress); S_SET_SEGMENT (def_symbol_in_progress, absolute_section); break; #ifndef STRICTCOFF case C_MOS: case C_MOE: case C_MOU: case C_EOS: S_SET_SEGMENT (def_symbol_in_progress, absolute_section); break; #endif case C_EXT: case C_WEAKEXT: #ifdef TE_PE case C_NT_WEAK: #endif case C_STAT: case C_LABEL: /* Valid but set somewhere else (s_comm, s_lcomm, colon). */ break; default: case C_USTATIC: case C_EXTDEF: case C_ULABEL: as_warn (_("unexpected storage class %d"), S_GET_STORAGE_CLASS (def_symbol_in_progress)); break; } /* Now that we have built a debug symbol, try to find if we should merge with an existing symbol or not. If a symbol is C_EFCN or absolute_section or untagged SEG_DEBUG it never merges. We also don't merge labels, which are in a different namespace, nor symbols which have not yet been defined since they are typically unique, nor do we merge tags with non-tags. */ /* Two cases for functions. Either debug followed by definition or definition followed by debug. For definition first, we will merge the debug symbol into the definition. For debug first, the lineno entry MUST point to the definition function or else it will point off into space when obj_crawl_symbol_chain() merges the debug symbol into the real symbol. Therefor, let's presume the debug symbol is a real function reference. */ /* FIXME-SOON If for some reason the definition label/symbol is never seen, this will probably leave an undefined symbol at link time. */ if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL || (streq (bfd_get_section_name (stdoutput, S_GET_SEGMENT (def_symbol_in_progress)), "*DEBUG*") && !SF_GET_TAG (def_symbol_in_progress)) || S_GET_SEGMENT (def_symbol_in_progress) == absolute_section || ! symbol_constant_p (def_symbol_in_progress) || (symbolP = symbol_find (S_GET_NAME (def_symbol_in_progress))) == NULL || SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP)) { /* If it already is at the end of the symbol list, do nothing */ if (def_symbol_in_progress != symbol_lastP) { symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); } } else { /* This symbol already exists, merge the newly created symbol into the old one. This is not mandatory. The linker can handle duplicate symbols correctly. But I guess that it save a *lot* of space if the assembly file defines a lot of symbols. [loic] */ /* The debug entry (def_symbol_in_progress) is merged into the previous definition. */ c_symbol_merge (def_symbol_in_progress, symbolP); symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); def_symbol_in_progress = symbolP; if (SF_GET_FUNCTION (def_symbol_in_progress) || SF_GET_TAG (def_symbol_in_progress) || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_STAT) { /* For functions, and tags, and static symbols, the symbol *must* be where the debug symbol appears. Move the existing symbol to the current place. */ /* If it already is at the end of the symbol list, do nothing. */ if (def_symbol_in_progress != symbol_lastP) { symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP); symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP); } } } if (SF_GET_TAG (def_symbol_in_progress)) { symbolS *oldtag; oldtag = symbol_find (S_GET_NAME (def_symbol_in_progress)); if (oldtag == NULL || ! SF_GET_TAG (oldtag)) tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress); } if (SF_GET_FUNCTION (def_symbol_in_progress)) { know (sizeof (def_symbol_in_progress) <= sizeof (long)); set_function (def_symbol_in_progress); SF_SET_PROCESS (def_symbol_in_progress); if (symbolP == NULL) /* That is, if this is the first time we've seen the function. */ symbol_table_insert (def_symbol_in_progress); } def_symbol_in_progress = NULL; demand_empty_rest_of_line (); }
// Parse macro call ("+MACROTITLE"). Has to be re-entrant. void Macro_parse_call(void) // Now GotByte = dot or first char of macro name { char local_gotbyte; struct symbol *symbol; struct section new_section, *outer_section; struct input new_input, *outer_input; struct macro *actual_macro; struct rwnode *macro_node, *symbol_node; zone_t macro_zone, symbol_zone; int arg_count = 0; // Enter deeper nesting level // Quit program if recursion too deep. if (--macro_recursions_left < 0) Throw_serious_error("Too deeply nested. Recursive macro calls?"); macro_zone = get_zone_and_title(); // now GotByte = first non-space after title // internal_name = MacroTitle ARG_SEPARATOR (grows to signature) // Accept n>=0 comma-separated arguments before CHAR_EOS. // Valid argument formats are: // EXPRESSION (everything that does NOT start with '~' // ~.LOCAL_LABEL_BY_REFERENCE // ~GLOBAL_LABEL_BY_REFERENCE // now GotByte = non-space if (GotByte != CHAR_EOS) { // any at all? do { // if arg table cannot take another element, enlarge if (argtable_size <= arg_count) enlarge_arg_table(); // Decide whether call-by-reference or call-by-value // In both cases, GlobalDynaBuf may be used. if (GotByte == REFERENCE_CHAR) { // read call-by-reference arg DynaBuf_append(internal_name, ARGTYPE_NUM_REF); GetByte(); // skip '~' character Input_read_zone_and_keyword(&symbol_zone); // GotByte = illegal char arg_table[arg_count].symbol = symbol_find(symbol_zone, 0); } else { // read call-by-value arg DynaBuf_append(internal_name, ARGTYPE_NUM_VAL); ALU_any_result(&(arg_table[arg_count].result)); } ++arg_count; } while (Input_accept_comma()); } // now arg_table contains the arguments // now GlobalDynaBuf = unused // check for "unknown macro" // Search for macro. Do not create if not found. search_for_macro(¯o_node, macro_zone, FALSE); if (macro_node == NULL) { Throw_error("Macro not defined (or wrong signature)."); Input_skip_remainder(); } else { // make macro_node point to the macro struct actual_macro = macro_node->body; local_gotbyte = GotByte; // CAUTION - ugly kluge // set up new input new_input.original_filename = actual_macro->def_filename; new_input.line_number = actual_macro->def_line_number; new_input.source_is_ram = TRUE; new_input.state = INPUTSTATE_NORMAL; // FIXME - fix others! new_input.src.ram_ptr = actual_macro->parameter_list; // remember old input outer_input = Input_now; // activate new input Input_now = &new_input; // remember old section outer_section = Section_now; // start new section (with new zone) // FALSE = title mustn't be freed Section_new_zone(&new_section, "Macro", actual_macro->original_name, FALSE); GetByte(); // fetch first byte of parameter list // assign arguments if (GotByte != CHAR_EOS) { // any at all? arg_count = 0; do { // Decide whether call-by-reference // or call-by-value // In both cases, GlobalDynaBuf may be used. if (GotByte == REFERENCE_CHAR) { // assign call-by-reference arg GetByte(); // skip '~' character Input_read_zone_and_keyword(&symbol_zone); if ((Tree_hard_scan(&symbol_node, symbols_forest, symbol_zone, TRUE) == FALSE) && (pass_count == 0)) Throw_error("Macro parameter twice."); symbol_node->body = arg_table[arg_count].symbol; } else { // assign call-by-value arg Input_read_zone_and_keyword(&symbol_zone); symbol = symbol_find(symbol_zone, 0); // FIXME - add a possibility to symbol_find to make it possible to find out // whether symbol was just created. Then check for the same error message here // as above ("Macro parameter twice."). symbol->result = arg_table[arg_count].result; } ++arg_count; } while (Input_accept_comma()); } // and now, finally, parse the actual macro body Input_now->state = INPUTSTATE_NORMAL; // FIXME - fix others! // maybe call parse_ram_block(actual_macro->def_line_number, actual_macro->body) Input_now->src.ram_ptr = actual_macro->body; Parse_until_eob_or_eof(); if (GotByte != CHAR_EOB) Bug_found("IllegalBlockTerminator", GotByte); // end section (free title memory, if needed) Section_finalize(&new_section); // restore previous section Section_now = outer_section; // restore previous input: Input_now = outer_input; // restore old Gotbyte context GotByte = local_gotbyte; // CAUTION - ugly kluge Input_ensure_EOS(); } ++macro_recursions_left; // leave this nesting level }