mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
* doc/as.texinfo (Reloc): Document.
* read.c (potable): Add "reloc". (s_reloc): New function. * write.c (reloc_list): New global var. (resolve_reloc_expr_symbols): New function. (write_object_file): Call it. (write_relocs): Process reloc_list. * write.h (struct reloc_list): New. (reloc_list): Declare.
This commit is contained in:
parent
157090f728
commit
05e9452c82
@ -1,3 +1,15 @@
|
||||
2007-03-26 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* doc/as.texinfo (Reloc): Document.
|
||||
* read.c (potable): Add "reloc".
|
||||
(s_reloc): New function.
|
||||
* write.c (reloc_list): New global var.
|
||||
(resolve_reloc_expr_symbols): New function.
|
||||
(write_object_file): Call it.
|
||||
(write_relocs): Process reloc_list.
|
||||
* write.h (struct reloc_list): New.
|
||||
(reloc_list): Declare.
|
||||
|
||||
2007-03-24 Paul Brook <paul@codesourcery.com>
|
||||
|
||||
* config/tc-arm.c (do_t_ldmstm): Error on Thumb-2 addressing modes.
|
||||
|
@ -3886,6 +3886,7 @@ Some machine configurations provide additional directives.
|
||||
@end ifset
|
||||
|
||||
* Quad:: @code{.quad @var{bignums}}
|
||||
* Reloc:: @code{.reloc @var{offset}, @var{reloc_name}[, @var{expression}]}
|
||||
* Rept:: @code{.rept @var{count}}
|
||||
* Sbttl:: @code{.sbttl "@var{subheading}"}
|
||||
@ifset COFF
|
||||
@ -5433,6 +5434,20 @@ warning message; and just takes the lowest order 16 bytes of the bignum.
|
||||
@cindex integer, 16-byte
|
||||
@end ifset
|
||||
|
||||
@node Reloc
|
||||
@section @code{.reloc @var{offset}, @var{reloc_name}[, @var{expression}]}
|
||||
|
||||
@cindex @code{reloc} directive
|
||||
Generate a relocation at @var{offset} of type @var{reloc_name} with value
|
||||
@var{expression}. If @var{offset} is a number, the relocation is generated in
|
||||
the current section. If @var{offset} is an expression that resolves to a
|
||||
symbol plus offset, the relocation is generated in the given symbol's section.
|
||||
@var{expression}, if present, must resolve to a symbol plus addend or to an
|
||||
absolute value, but note that not all targets support an addend. e.g. ELF REL
|
||||
targets such as i386 store an addend in the section contents rather than in the
|
||||
relocation. This low level interface does not support addends stored in the
|
||||
section.
|
||||
|
||||
@node Rept
|
||||
@section @code{.rept @var{count}}
|
||||
|
||||
|
109
gas/read.c
109
gas/read.c
@ -213,6 +213,7 @@ static void do_align (int, char *, int, int);
|
||||
static void s_align (int, int);
|
||||
static void s_altmacro (int);
|
||||
static void s_bad_end (int);
|
||||
static void s_reloc (int);
|
||||
static int hex_float (int, char *);
|
||||
static segT get_known_segmented_expression (expressionS * expP);
|
||||
static void pobegin (void);
|
||||
@ -391,6 +392,7 @@ static const pseudo_typeS potable[] = {
|
||||
{"psize", listing_psize, 0}, /* Set paper size. */
|
||||
{"purgem", s_purgem, 0},
|
||||
{"quad", cons, 8},
|
||||
{"reloc", s_reloc, 0},
|
||||
{"rep", s_rept, 0},
|
||||
{"rept", s_rept, 0},
|
||||
{"rva", s_rva, 4},
|
||||
@ -3669,6 +3671,113 @@ s_rva (int size)
|
||||
cons_worker (size, 1);
|
||||
}
|
||||
|
||||
/* .reloc offset, reloc_name, symbol+addend. */
|
||||
|
||||
void
|
||||
s_reloc (int ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
char *stop = NULL;
|
||||
char stopc = 0;
|
||||
expressionS exp;
|
||||
char *r_name;
|
||||
int c;
|
||||
struct reloc_list *reloc;
|
||||
|
||||
reloc = xmalloc (sizeof (*reloc));
|
||||
|
||||
if (flag_mri)
|
||||
stop = mri_comment_field (&stopc);
|
||||
|
||||
expression (&exp);
|
||||
switch (exp.X_op)
|
||||
{
|
||||
case O_illegal:
|
||||
case O_absent:
|
||||
case O_big:
|
||||
case O_register:
|
||||
as_bad (_("missing or bad offset expression"));
|
||||
goto err_out;
|
||||
case O_constant:
|
||||
exp.X_add_symbol = section_symbol (now_seg);
|
||||
exp.X_op = O_symbol;
|
||||
/* Fall thru */
|
||||
case O_symbol:
|
||||
if (exp.X_add_number == 0)
|
||||
{
|
||||
reloc->u.a.offset_sym = exp.X_add_symbol;
|
||||
break;
|
||||
}
|
||||
/* Fall thru */
|
||||
default:
|
||||
reloc->u.a.offset_sym = make_expr_symbol (&exp);
|
||||
break;
|
||||
}
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer != ',')
|
||||
{
|
||||
as_bad (_("missing reloc type"));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
++input_line_pointer;
|
||||
SKIP_WHITESPACE ();
|
||||
r_name = input_line_pointer;
|
||||
c = get_symbol_end ();
|
||||
reloc->u.a.howto = bfd_reloc_name_lookup (stdoutput, r_name);
|
||||
*input_line_pointer = c;
|
||||
if (reloc->u.a.howto == NULL)
|
||||
{
|
||||
as_bad (_("unrecognized reloc type"));
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
exp.X_op = O_absent;
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer == ',')
|
||||
{
|
||||
++input_line_pointer;
|
||||
expression_and_evaluate (&exp);
|
||||
}
|
||||
switch (exp.X_op)
|
||||
{
|
||||
case O_illegal:
|
||||
case O_big:
|
||||
case O_register:
|
||||
as_bad (_("bad reloc expression"));
|
||||
err_out:
|
||||
ignore_rest_of_line ();
|
||||
free (reloc);
|
||||
if (flag_mri)
|
||||
mri_comment_end (stop, stopc);
|
||||
return;
|
||||
case O_absent:
|
||||
reloc->u.a.sym = NULL;
|
||||
reloc->u.a.addend = 0;
|
||||
break;
|
||||
case O_constant:
|
||||
reloc->u.a.sym = NULL;
|
||||
reloc->u.a.addend = exp.X_add_number;
|
||||
break;
|
||||
case O_symbol:
|
||||
reloc->u.a.sym = exp.X_add_symbol;
|
||||
reloc->u.a.addend = exp.X_add_number;
|
||||
break;
|
||||
default:
|
||||
reloc->u.a.sym = make_expr_symbol (&exp);
|
||||
reloc->u.a.addend = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
as_where (&reloc->file, &reloc->line);
|
||||
reloc->next = reloc_list;
|
||||
reloc_list = reloc;
|
||||
|
||||
demand_empty_rest_of_line ();
|
||||
if (flag_mri)
|
||||
mri_comment_end (stop, stopc);
|
||||
}
|
||||
|
||||
/* Put the contents of expression EXP into the object file using
|
||||
NBYTES bytes. If need_pass_2 is 1, this does nothing. */
|
||||
|
||||
|
118
gas/write.c
118
gas/write.c
@ -117,6 +117,9 @@ symbolS *abs_section_sym;
|
||||
/* Remember the value of dot when parsing expressions. */
|
||||
addressT dot_value;
|
||||
|
||||
/* Relocs generated by ".reloc" pseudo. */
|
||||
struct reloc_list* reloc_list;
|
||||
|
||||
void print_fixup (fixS *);
|
||||
|
||||
/* We generally attach relocs to frag chains. However, after we have
|
||||
@ -624,6 +627,86 @@ dump_section_relocs (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, FILE *stream)
|
||||
#define EMIT_SECTION_SYMBOLS 1
|
||||
#endif
|
||||
|
||||
/* Resolve U.A.OFFSET_SYM and U.A.SYM fields of RELOC_LIST entries,
|
||||
and check for validity. Convert RELOC_LIST from using U.A fields
|
||||
to U.B fields. */
|
||||
static void
|
||||
resolve_reloc_expr_symbols (void)
|
||||
{
|
||||
struct reloc_list *r;
|
||||
|
||||
for (r = reloc_list; r; r = r->next)
|
||||
{
|
||||
expressionS *symval;
|
||||
symbolS *sym;
|
||||
bfd_vma offset, addend;
|
||||
asection *sec;
|
||||
reloc_howto_type *howto;
|
||||
|
||||
resolve_symbol_value (r->u.a.offset_sym);
|
||||
symval = symbol_get_value_expression (r->u.a.offset_sym);
|
||||
|
||||
offset = 0;
|
||||
sym = NULL;
|
||||
if (symval->X_op == O_constant)
|
||||
sym = r->u.a.offset_sym;
|
||||
else if (symval->X_op == O_symbol)
|
||||
{
|
||||
sym = symval->X_add_symbol;
|
||||
offset = symval->X_add_number;
|
||||
symval = symbol_get_value_expression (symval->X_add_symbol);
|
||||
}
|
||||
if (sym == NULL
|
||||
|| symval->X_op != O_constant
|
||||
|| (sec = S_GET_SEGMENT (sym)) == NULL
|
||||
|| !SEG_NORMAL (sec))
|
||||
{
|
||||
as_bad_where (r->file, r->line, _("invalid offset expression"));
|
||||
sec = NULL;
|
||||
}
|
||||
else
|
||||
offset += S_GET_VALUE (sym);
|
||||
|
||||
sym = NULL;
|
||||
addend = r->u.a.addend;
|
||||
if (r->u.a.sym != NULL)
|
||||
{
|
||||
resolve_symbol_value (r->u.a.sym);
|
||||
symval = symbol_get_value_expression (r->u.a.sym);
|
||||
if (symval->X_op == O_constant)
|
||||
sym = r->u.a.sym;
|
||||
else if (symval->X_op == O_symbol)
|
||||
{
|
||||
sym = symval->X_add_symbol;
|
||||
addend += symval->X_add_number;
|
||||
symval = symbol_get_value_expression (symval->X_add_symbol);
|
||||
}
|
||||
if (symval->X_op != O_constant)
|
||||
{
|
||||
as_bad_where (r->file, r->line, _("invalid reloc expression"));
|
||||
sec = NULL;
|
||||
}
|
||||
else if (sym != NULL)
|
||||
symbol_mark_used_in_reloc (sym);
|
||||
}
|
||||
if (sym == NULL)
|
||||
{
|
||||
if (abs_section_sym == NULL)
|
||||
abs_section_sym = section_symbol (absolute_section);
|
||||
sym = abs_section_sym;
|
||||
}
|
||||
|
||||
howto = r->u.a.howto;
|
||||
|
||||
r->u.b.sec = sec;
|
||||
r->u.b.s = symbol_get_bfdsym (sym);
|
||||
r->u.b.r.sym_ptr_ptr = &r->u.b.s;
|
||||
r->u.b.r.address = offset;
|
||||
r->u.b.r.addend = addend;
|
||||
r->u.b.r.howto = howto;
|
||||
}
|
||||
}
|
||||
|
||||
/* This pass over fixups decides whether symbols can be replaced with
|
||||
section symbols. */
|
||||
|
||||
@ -1027,6 +1110,7 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
|
||||
segment_info_type *seginfo = seg_info (sec);
|
||||
unsigned int i;
|
||||
unsigned int n;
|
||||
struct reloc_list *my_reloc_list, **rp, *r;
|
||||
arelent **relocs;
|
||||
fixS *fixp;
|
||||
|
||||
@ -1044,6 +1128,22 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
|
||||
n *= MAX_RELOC_EXPANSION;
|
||||
#endif
|
||||
|
||||
/* Extract relocs for this section from reloc_list. */
|
||||
rp = &reloc_list;
|
||||
my_reloc_list = NULL;
|
||||
while ((r = *rp) != NULL)
|
||||
{
|
||||
if (r->u.b.sec == sec)
|
||||
{
|
||||
*rp = r->next;
|
||||
r->next = my_reloc_list;
|
||||
my_reloc_list = r;
|
||||
n++;
|
||||
}
|
||||
else
|
||||
rp = &r->next;
|
||||
}
|
||||
|
||||
relocs = xcalloc (n, sizeof (arelent *));
|
||||
|
||||
i = 0;
|
||||
@ -1107,6 +1207,23 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
|
||||
}
|
||||
#endif
|
||||
|
||||
for (r = my_reloc_list; r != NULL; r = r->next)
|
||||
{
|
||||
fragS *f;
|
||||
for (f = seginfo->frchainP->frch_root; f; f = f->fr_next)
|
||||
if (f->fr_address <= r->u.b.r.address
|
||||
&& r->u.b.r.address < f->fr_address + f->fr_fix)
|
||||
break;
|
||||
if (f == NULL)
|
||||
as_bad_where (r->file, r->line,
|
||||
_("reloc not within (fixed part of) section"));
|
||||
else
|
||||
{
|
||||
relocs[n++] = &r->u.b.r;
|
||||
install_reloc (sec, &r->u.b.r, f, r->file, r->line);
|
||||
}
|
||||
}
|
||||
|
||||
if (n)
|
||||
{
|
||||
flagword flags = bfd_get_section_flags (abfd, sec);
|
||||
@ -1564,6 +1681,7 @@ write_object_file (void)
|
||||
resolve_symbol_value (symp);
|
||||
}
|
||||
resolve_local_symbol_values ();
|
||||
resolve_reloc_expr_symbols ();
|
||||
|
||||
PROGRESS (1);
|
||||
|
||||
|
24
gas/write.h
24
gas/write.h
@ -142,11 +142,35 @@ struct fix
|
||||
|
||||
typedef struct fix fixS;
|
||||
|
||||
struct reloc_list
|
||||
{
|
||||
struct reloc_list *next;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
symbolS *offset_sym;
|
||||
reloc_howto_type *howto;
|
||||
symbolS *sym;
|
||||
bfd_vma addend;
|
||||
} a;
|
||||
struct
|
||||
{
|
||||
asection *sec;
|
||||
asymbol *s;
|
||||
arelent r;
|
||||
} b;
|
||||
} u;
|
||||
char *file;
|
||||
unsigned int line;
|
||||
};
|
||||
|
||||
extern int finalize_syms;
|
||||
extern symbolS *abs_section_sym;
|
||||
extern addressT dot_value;
|
||||
extern long string_byte_count;
|
||||
extern int section_alignment[];
|
||||
extern struct reloc_list* reloc_list;
|
||||
|
||||
extern void append (char **charPP, char *fromP, unsigned long length);
|
||||
extern void record_alignment (segT seg, int align);
|
||||
|
Loading…
Reference in New Issue
Block a user