aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ldexp.c140
-rw-r--r--ld/ldgram.y8
-rw-r--r--ld/ldlang.c38
-rw-r--r--ld/ldlex.l66
4 files changed, 135 insertions, 117 deletions
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 02fb314..a85c79e 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -281,82 +281,94 @@ bfd_vma dot;
{
etree_value_type result;
switch (tree->type.node_code)
- {
- case DEFINED:
- result.value =
- ldsym_get_soft(tree->name.name) != (ldsym_type *)NULL;
- result.section = 0;
- result.valid = true;
- break;
- case NAME:
- result.valid = false;
- if (tree->name.name[0] == '.' && tree->name.name[1] == 0) {
-
- if (allocation_done != lang_first_phase_enum) {
- result = new_rel_from_section(dot, current_section);
+ {
+ case DEFINED:
+ result.value =
+ ldsym_get_soft(tree->name.name) != (ldsym_type *)NULL;
+ result.section = 0;
+ result.valid = true;
+ break;
+ case NAME:
+ result.valid = false;
+ if (tree->name.name[0] == '.' && tree->name.name[1] == 0) {
+
+ if (allocation_done != lang_first_phase_enum) {
+ result = new_rel_from_section(dot, current_section);
+ }
+ else {
+ result = invalid();
+ }
}
else {
- result = invalid();
- }
- }
- else {
- if (allocation_done == lang_final_phase_enum) {
- ldsym_type *sy = ldsym_get_soft(tree->name.name);
+ if (allocation_done == lang_final_phase_enum) {
+ ldsym_type *sy = ldsym_get_soft(tree->name.name);
- if (sy) {
- asymbol **sdefp = sy->sdefs_chain;
-
- if (sdefp) {
- asymbol *sdef = *sdefp;
- if (sdef->section == (asection *)NULL) {
- /* This is an absolute symbol */
- result = new_abs(sdef->value);
- }
- else {
- lang_output_section_statement_type *os =
- lang_output_section_statement_lookup( sdef->section->output_section->name);
- result = new_rel(sdef->value, os);
+ if (sy) {
+ asymbol **sdefp = sy->sdefs_chain;
+
+ if (sdefp) {
+ asymbol *sdef = *sdefp;
+ if (sdef->section == (asection *)NULL) {
+ /* This is an absolute symbol */
+ result = new_abs(sdef->value);
+ }
+ else {
+ lang_output_section_statement_type *os =
+ lang_output_section_statement_lookup(
+ sdef->section->output_section->name);
+ /* If the symbol is from a file which we are not
+ relocating (-R) then return an absolute for its
+ value */
+ if (sdef->the_bfd->usrdata &&
+ ((lang_input_statement_type*)(sdef->the_bfd->usrdata))->just_syms_flag == true)
+ {
+ result = new_abs(sdef->value + sdef->section ?
+ sdef->section->vma : 0);
+ }
+ else {
+ result = new_rel(sdef->value, os);
+ }
+ }
}
}
- }
- if (result.valid == false) {
- info("%F%S: undefined symbol `%s' referenced in expression.\n",
+ if (result.valid == false) {
+ info("%F%S: undefined symbol `%s' referenced in expression.\n",
tree->name.name);
- }
+ }
+ }
}
- }
- break;
+ break;
- case ADDR:
+ case ADDR:
- if (allocation_done != lang_first_phase_enum) {
- lang_output_section_statement_type *os =
- lang_output_section_find(tree->name.name);
- check(os,tree->name.name,"ADDR");
- result = new_rel((bfd_vma)0, os);
- }
- else {
- result = invalid();
- }
- break;
- case SIZEOF:
- if(allocation_done != lang_first_phase_enum) {
- lang_output_section_statement_type *os =
- lang_output_section_find(tree->name.name);
- check(os,tree->name.name,"SIZEOF");
- result = new_abs((bfd_vma)(os->bfd_section->size));
- }
- else {
- result = invalid();
- }
- break;
+ if (allocation_done != lang_first_phase_enum) {
+ lang_output_section_statement_type *os =
+ lang_output_section_find(tree->name.name);
+ check(os,tree->name.name,"ADDR");
+ result = new_rel((bfd_vma)0, os);
+ }
+ else {
+ result = invalid();
+ }
+ break;
+ case SIZEOF:
+ if(allocation_done != lang_first_phase_enum) {
+ lang_output_section_statement_type *os =
+ lang_output_section_find(tree->name.name);
+ check(os,tree->name.name,"SIZEOF");
+ result = new_abs((bfd_vma)(os->bfd_section->size));
+ }
+ else {
+ result = invalid();
+ }
+ break;
- default:
- FAIL();
- break;
- }
+ default:
+ FAIL();
+ break;
+ }
return result;
}
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 2e0e501..304b0b2 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -151,7 +151,11 @@ command_line:
;
command_line_option:
- SCRIPT ifile_list ENDSCRIPT
+ SCRIPT
+ { ldgram_in_script = true; }
+ ifile_list
+ { ldgram_in_script = false; }
+ ENDSCRIPT
| OPTION_v
{
ldversion();
@@ -318,7 +322,7 @@ ifile_p1:
| high_level_library
| low_level_library
| floating_point_support
- | assignment end
+ | statement_anywhere
| TARGET_K '(' NAME ')'
{ lang_add_target($3); }
| SEARCH_DIR '(' filename ')'
diff --git a/ld/ldlang.c b/ld/ldlang.c
index e63f899..afbc385 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -1247,23 +1247,28 @@ DEFUN(size_input_section, (this_ptr, output_section_statement, fill, dot),
asection *i = is->section;
if (is->ifile->just_syms_flag == false) {
- dot = insert_pad(this_ptr, fill, i->alignment_power,
- output_section_statement->bfd_section, dot);
+ dot = insert_pad(this_ptr, fill, i->alignment_power,
+ output_section_statement->bfd_section, dot);
- /* remember the largest size so we can malloc the largest area */
- /* needed for the output stage */
- if (i->size > largest_section) {
- largest_section = i->size;
- }
+ /* remember the largest size so we can malloc the largest area */
+ /* needed for the output stage */
+ if (i->size > largest_section) {
+ largest_section = i->size;
+ }
- /* Remember where in the output section this input section goes */
- i->output_offset = dot - output_section_statement->bfd_section->vma;
+ /* Remember where in the output section this input section goes */
- /* Mark how big the output section must be to contain this now */
- dot += i->size;
- output_section_statement->bfd_section->size =
- dot - output_section_statement->bfd_section->vma;
-}
+ i->output_offset = dot - output_section_statement->bfd_section->vma;
+
+ /* Mark how big the output section must be to contain this now */
+ dot += i->size;
+ output_section_statement->bfd_section->size =
+ dot - output_section_statement->bfd_section->vma;
+ }
+ else
+ {
+ i->output_offset = i->vma - output_section_statement->bfd_section->vma;
+ }
return dot ;
}
@@ -1718,8 +1723,10 @@ DEFUN_VOID(lang_common)
com->section->alignment_power = power_of_two;
}
+ /* Symbol stops being common and starts being global, but
+ we remember that it was common once. */
- com->flags = BSF_EXPORT | BSF_GLOBAL ;
+ com->flags = BSF_EXPORT | BSF_GLOBAL | BSF_OLD_COMMON;
if (write_map)
@@ -1731,7 +1738,6 @@ DEFUN_VOID(lang_common)
}
com->value = com->section->size;
com->section->size += size;
- com->the_bfd = output_bfd;
}
diff --git a/ld/ldlex.l b/ld/ldlex.l
index 82f6659..dd67083 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -383,27 +383,6 @@ WHITE [ \t]+
yylval.name[yyleng-2] = 0; /* Fry final quote */
return NAME;
}
-[0][0-7KM]* {
-
- yylval.integer = number(yytext+1, 8);
- return INT;
-}
-
-[0-9]+[KM]? {
- if (hex_mode == true || ldgram_in_defsym == true) {
- yylval.integer = number(yytext, 16);
- }
- else {
- yylval.integer = number(yytext, 10);
- }
- return INT;
-}
-
-0[Xx][0-9a-fA-FKM]+ {
-
- yylval.integer = number(yytext+2,16);
- return INT;
-}
"\#"{WHITE}*{FILENAMECHAR}+ {
char *p = yytext+1;
@@ -439,17 +418,34 @@ WHITE [ \t]+
int ch;
keyword_type *k;
- if (hex_mode) {
- ch = yytext[0];
- /* Then always read a number */
- while (isxdigit(ch)) {
- yytext[yyleng++] = ch;
- ch = input();
+ if ((hex_mode && isxdigit(yytext[0]))
+ ||
+ (isdigit(yytext[0]) && (ldgram_in_expression == true || ldgram_in_script == true))) {
+ char *start = yytext;
+ unsigned int base = 10;
+ if (hex_mode == true) base = 16;
+ if (yytext[0] == '0') {
+ base = 8;
}
+ ch = input();
+ while (isxdigit(ch)
+ || ch == 'x'
+ || ch == 'X'
+ || ch == 'M'
+ )
+ {
+ if (ch == 'x' || ch == 'X') {
+ base = 16;
+ start = yytext + yyleng;
+ }
+ else {
+ yytext[yyleng++] = ch;
+ }
+ ch = input();
+ }
yytext[yyleng] = 0;
unput(ch);
-
- yylval.integer = number(yytext,16);
+ yylval.integer = number(start, base);
return INT;
}
@@ -462,8 +458,8 @@ WHITE [ \t]+
- /* Otherwise we only notice special things if were in an
- expression */
+ /* Otherwise we only notice special things if were in an
+ expression */
if (ldgram_in_expression) {
if (yytext[0] != '/' || ldgram_in_defsym == false) {
@@ -482,10 +478,10 @@ WHITE [ \t]+
if (isalpha(ch) || isdigit(ch) || ch == '.' || ch == '_' ) {
yytext[yyleng++] = ch;
}
-else if (ch == '=' && ldgram_in_script) {
-/* An = within a script is always taken to be an operator */
-break;
-}
+ else if (ch == '=' && ldgram_in_script) {
+ /* An = within a script is always taken to be an operator */
+ break;
+ }
else if (ch == '+' || ch == '-' || ch == '/' || ch == '=') {
if (ldgram_in_expression) break;
yytext[yyleng++] = ch;