📄 som.c
字号:
{ bfd_put_8 (abfd, R_NO_RELOCATION + 24 + (((skip >> 2) - 1) >> 8), p); bfd_put_8 (abfd, (skip >> 2) - 1, p + 1); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue); } /* Handle it with a three byte R_NO_RELOCATION entry. */ else { bfd_put_8 (abfd, R_NO_RELOCATION + 28 + (((skip >> 2) - 1) >> 16), p); bfd_put_16 (abfd, (skip >> 2) - 1, p + 1); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue); } } /* Ugh. Punt and use a 4 byte entry. */ else if (skip > 0) { bfd_put_8 (abfd, R_NO_RELOCATION + 31, p); bfd_put_8 (abfd, (skip - 1) >> 16, p + 1); bfd_put_16 (abfd, skip - 1, p + 2); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue); } return p;}/* Emit the proper R_DATA_OVERRIDE fixups to handle a nonzero addend from a BFD relocation. Update the size of the subspace relocation stream via SUBSPACE_RELOC_SIZE_P; also return the current pointer into the relocation stream. */static unsigned char *som_reloc_addend (abfd, addend, p, subspace_reloc_sizep, queue) bfd *abfd; int addend; unsigned char *p; unsigned int *subspace_reloc_sizep; struct reloc_queue *queue;{ if ((unsigned) (addend) + 0x80 < 0x100) { bfd_put_8 (abfd, R_DATA_OVERRIDE + 1, p); bfd_put_8 (abfd, addend, p + 1); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue); } else if ((unsigned) (addend) + 0x8000 < 0x10000) { bfd_put_8 (abfd, R_DATA_OVERRIDE + 2, p); bfd_put_16 (abfd, addend, p + 1); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue); } else if ((unsigned) (addend) + 0x800000 < 0x1000000) { bfd_put_8 (abfd, R_DATA_OVERRIDE + 3, p); bfd_put_8 (abfd, addend >> 16, p + 1); bfd_put_16 (abfd, addend, p + 2); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 4, queue); } else { bfd_put_8 (abfd, R_DATA_OVERRIDE + 4, p); bfd_put_32 (abfd, addend, p + 1); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue); } return p;}/* Handle a single function call relocation. */static unsigned char *som_reloc_call (abfd, p, subspace_reloc_sizep, bfd_reloc, sym_num, queue) bfd *abfd; unsigned char *p; unsigned int *subspace_reloc_sizep; arelent *bfd_reloc; int sym_num; struct reloc_queue *queue;{ int arg_bits = HPPA_R_ARG_RELOC (bfd_reloc->addend); int rtn_bits = arg_bits & 0x3; int type, done = 0; /* You'll never believe all this is necessary to handle relocations for function calls. Having to compute and pack the argument relocation bits is the real nightmare. If you're interested in how this works, just forget it. You really do not want to know about this braindamage. */ /* First see if this can be done with a "simple" relocation. Simple relocations have a symbol number < 0x100 and have simple encodings of argument relocations. */ if (sym_num < 0x100) { switch (arg_bits) { case 0: case 1: type = 0; break; case 1 << 8: case 1 << 8 | 1: type = 1; break; case 1 << 8 | 1 << 6: case 1 << 8 | 1 << 6 | 1: type = 2; break; case 1 << 8 | 1 << 6 | 1 << 4: case 1 << 8 | 1 << 6 | 1 << 4 | 1: type = 3; break; case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2: case 1 << 8 | 1 << 6 | 1 << 4 | 1 << 2 | 1: type = 4; break; default: /* Not one of the easy encodings. This will have to be handled by the more complex code below. */ type = -1; break; } if (type != -1) { /* Account for the return value too. */ if (rtn_bits) type += 5; /* Emit a 2 byte relocation. Then see if it can be handled with a relocation which is already in the relocation queue. */ bfd_put_8 (abfd, bfd_reloc->howto->type + type, p); bfd_put_8 (abfd, sym_num, p + 1); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 2, queue); done = 1; } } /* If this could not be handled with a simple relocation, then do a hard one. Hard relocations occur if the symbol number was too high or if the encoding of argument relocation bits is too complex. */ if (! done) { /* Don't ask about these magic sequences. I took them straight from gas-1.36 which took them from the a.out man page. */ type = rtn_bits; if ((arg_bits >> 6 & 0xf) == 0xe) type += 9 * 40; else type += (3 * (arg_bits >> 8 & 3) + (arg_bits >> 6 & 3)) * 40; if ((arg_bits >> 2 & 0xf) == 0xe) type += 9 * 4; else type += (3 * (arg_bits >> 4 & 3) + (arg_bits >> 2 & 3)) * 4; /* Output the first two bytes of the relocation. These describe the length of the relocation and encoding style. */ bfd_put_8 (abfd, bfd_reloc->howto->type + 10 + 2 * (sym_num >= 0x100) + (type >= 0x100), p); bfd_put_8 (abfd, type, p + 1); /* Now output the symbol index and see if this bizarre relocation just happened to be in the relocation queue. */ if (sym_num < 0x100) { bfd_put_8 (abfd, sym_num, p + 2); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 3, queue); } else { bfd_put_8 (abfd, sym_num >> 16, p + 2); bfd_put_16 (abfd, sym_num, p + 3); p = try_prev_fixup (abfd, subspace_reloc_sizep, p, 5, queue); } } return p;}/* Return the logarithm of X, base 2, considering X unsigned. Abort -1 if X is not a power or two or is zero. */static intlog2 (x) unsigned int x;{ int log = 0; /* Test for 0 or a power of 2. */ if (x == 0 || x != (x & -x)) return -1; while ((x >>= 1) != 0) log++; return log;}static bfd_reloc_status_typehppa_som_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry; asymbol *symbol_in ATTRIBUTE_UNUSED; PTR data ATTRIBUTE_UNUSED; asection *input_section; bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED;{ if (output_bfd) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } return bfd_reloc_ok;}/* Given a generic HPPA relocation type, the instruction format, and a field selector, return one or more appropriate SOM relocations. */int **hppa_som_gen_reloc_type (abfd, base_type, format, field, sym_diff, sym) bfd *abfd; int base_type; int format; enum hppa_reloc_field_selector_type_alt field; int sym_diff; asymbol *sym;{ int *final_type, **final_types; final_types = (int **) bfd_alloc (abfd, sizeof (int *) * 6); final_type = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types || !final_type) return NULL; /* The field selector may require additional relocations to be generated. It's impossible to know at this moment if additional relocations will be needed, so we make them. The code to actually write the relocation/fixup stream is responsible for removing any redundant relocations. */ switch (field) { case e_fsel: case e_psel: case e_lpsel: case e_rpsel: final_types[0] = final_type; final_types[1] = NULL; final_types[2] = NULL; *final_type = base_type; break; case e_tsel: case e_ltsel: case e_rtsel: final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0]) return NULL; if (field == e_tsel) *final_types[0] = R_FSEL; else if (field == e_ltsel) *final_types[0] = R_LSEL; else *final_types[0] = R_RSEL; final_types[1] = final_type; final_types[2] = NULL; *final_type = base_type; break; case e_lssel: case e_rssel: final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0]) return NULL; *final_types[0] = R_S_MODE; final_types[1] = final_type; final_types[2] = NULL; *final_type = base_type; break; case e_lsel: case e_rsel: final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0]) return NULL; *final_types[0] = R_N_MODE; final_types[1] = final_type; final_types[2] = NULL; *final_type = base_type; break; case e_ldsel: case e_rdsel: final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0]) return NULL; *final_types[0] = R_D_MODE; final_types[1] = final_type; final_types[2] = NULL; *final_type = base_type; break; case e_lrsel: case e_rrsel: final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0]) return NULL; *final_types[0] = R_R_MODE; final_types[1] = final_type; final_types[2] = NULL; *final_type = base_type; break; case e_nsel: final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0]) return NULL; *final_types[0] = R_N1SEL; final_types[1] = final_type; final_types[2] = NULL; *final_type = base_type; break; case e_nlsel: case e_nlrsel: final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0]) return NULL; *final_types[0] = R_N0SEL; final_types[1] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[1]) return NULL; if (field == e_nlsel) *final_types[1] = R_N_MODE; else *final_types[1] = R_R_MODE; final_types[2] = final_type; final_types[3] = NULL; *final_type = base_type; break; } switch (base_type) { case R_HPPA: /* The difference of two symbols needs *very* special handling. */ if (sym_diff) { final_types[0] = (int *) bfd_alloc (abfd, sizeof (int)); final_types[1] = (int *) bfd_alloc (abfd, sizeof (int)); final_types[2] = (int *) bfd_alloc (abfd, sizeof (int)); final_types[3] = (int *) bfd_alloc (abfd, sizeof (int)); if (!final_types[0] || !final_types[1] || !final_types[2]) return NULL; if (field == e_fsel) *final_types[0] = R_FSEL; else if (field == e_rsel) *final_types[0] = R_RSEL; else if (field == e_lsel) *final_types[0] = R_LSEL; *final_types[1] = R_COMP2; *final_types[2] = R_COMP2; *final_types[3] = R_COMP1; final_types[4] = final_type; if (format == 32) *final_types[4] = R_DATA_EXPR; else *final_types[4] = R_CODE_EXPR; final_types[5] = NULL; break; } /* PLABELs get their own relocation type. */ else if (field == e_psel || field == e_lpsel || field == e_rpsel) { /* A PLABEL relocation that has a size of 32 bits must be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */ if (format == 32) *final_type = R_DATA_PLABEL; else *final_type = R_CODE_PLABEL; } /* PIC stuff. */ else if (field == e_tsel || field == e_ltsel || field == e_rtsel) *final_type = R_DLT_REL; /* A relocation in the data space is always a full 32bits. */ else if (format == 32) { *final_type = R_DATA_ONE_SYMBOL; /* If there's no SOM symbol type associated with this BFD symbol, then set the symbol type to ST_DATA. Only do this if the type is going to default later when we write the object file. This is done so that the linker never encounters an R_DATA_ONE_SYMBOL reloc involving an ST_CODE symbol. This allows the compiler to generate exception handling tables. Note that one day we may need to also emit BEGIN_BRTAB and END_BRTAB to prevent the linker from optimizing away insns in exception handling regions. */ if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN && (sym->flags & BSF_SECTION_SYM) == 0 && (sym->flags & BSF_FUNCTION) == 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -