as: support ".size <sym>,.-<sym>"

This commit is contained in:
Mikael Pettersson
2015-01-29 19:48:42 +00:00
parent 5c14e1a861
commit a037f1b991
5 changed files with 75 additions and 3 deletions

View File

@@ -71,6 +71,36 @@ static int do_dot_globl(struct scan_state *scan_state, struct tunit *tunit, stru
return 0;
}
static int do_dot_size(struct scan_state *scan_state, struct tunit *tunit, struct stmt *stmt)
{
struct symbol *symbol;
symbol = tunit_symbol_enter(tunit, stmt->u.symbol.name);
if (!symbol)
return -1;
if (!symbol->section
|| !symbol->defined) {
fprintf(stderr, "%s: %s line %u: symbol %s undefined\n",
scan_state->progname, scan_state->filename, scan_state->linenr, stmt->u.symbol.name);
return -1;
}
if (symbol->st_size) {
fprintf(stderr, "%s: %s line %u: size of symbol %s already defined\n",
scan_state->progname, scan_state->filename, scan_state->linenr, stmt->u.symbol.name);
return -1;
}
if (symbol->section != tunit->cursect) {
fprintf(stderr, "%s: %s line %u: symbol %s is not defined in current section\n",
scan_state->progname, scan_state->filename, scan_state->linenr, stmt->u.symbol.name);
return -1;
}
symbol->st_size = tunit->cursect->dot - symbol->st_value;
return 0;
}
static int do_dot_text(struct scan_state *scan_state, struct tunit *tunit, struct stmt *stmt)
{
struct section *section;
@@ -152,6 +182,8 @@ static int interpret(struct scan_state *scan_state, struct tunit *tunit, struct
return do_dot_file(scan_state, tunit, stmt);
case S_DOT_GLOBL:
return do_dot_globl(scan_state, tunit, stmt);
case S_DOT_SIZE:
return do_dot_size(scan_state, tunit, stmt);
case S_DOT_TEXT:
return do_dot_text(scan_state, tunit, stmt);
case S_DOT_TYPE_FUNCTION:

View File

@@ -53,6 +53,37 @@ static int parse_dot_globl(struct scan_state *scan_state, struct stmt *stmt)
return error(scan_state, "junk after .globl directive", token, &token_attr);
}
/* for now, accepts: .size <sym>,.-<sym> */
static int parse_dot_size(struct scan_state *scan_state, struct stmt *stmt)
{
enum token token;
union token_attribute token_attr;
token = scan_token(scan_state, &token_attr);
if (token == T_SYMBOL) {
stmt->u.symbol.name = token_attr.text;
token = scan_token(scan_state, &token_attr);
if (token == T_COMMA) {
token = scan_token(scan_state, &token_attr);
if (token == T_DOT) {
token = scan_token(scan_state, &token_attr);
if (token == T_MINUS) {
token = scan_token(scan_state, &token_attr);
if (token == T_SYMBOL
&& strcmp(token_attr.text, stmt->u.symbol.name) == 0) {
token = scan_token(scan_state, &token_attr);
if (token == T_NEWLINE) {
stmt->tag = S_DOT_SIZE;
return 1;
}
}
}
}
}
}
return error(scan_state, "junk after .size directive", token, &token_attr);
}
static int parse_dot_text(struct scan_state *scan_state, struct stmt *stmt)
{
enum token token;
@@ -378,6 +409,8 @@ int parse_stmt(struct scan_state *scan_state, struct stmt *stmt)
return parse_dot_file(scan_state, stmt);
case T_DOT_GLOBL:
return parse_dot_globl(scan_state, stmt);
case T_DOT_SIZE:
return parse_dot_size(scan_state, stmt);
case T_DOT_TEXT:
return parse_dot_text(scan_state, stmt);
case T_DOT_TYPE:

View File

@@ -220,6 +220,9 @@ static enum token do_symbol(struct scan_state *scan_state, union token_attribute
if (charbuf[0] == '.') {
enum token low, high;
if (charbuf[1] == '\0')
return T_DOT;
/* see token.def, reserved symbols occupy tokens [0,T_SYMBOL[ */
low = 0;
high = T_SYMBOL;
@@ -322,6 +325,8 @@ enum token scan_token(struct scan_state *scan_state, union token_attribute *toke
return T_RPAREN;
case '"':
return do_string(scan_state, token_attr);
case '-':
return T_MINUS;
case '.':
/* Dot may start a floating point literal, but tests show that
gcc always outputs floating point values as integer literals,

View File

@@ -7,6 +7,7 @@
/* reserved symbols including directives; MUST come first and MUST be listed in increasing alphanumeric order */
TOKEN(T_DOT_FILE, ".file", TAFMT_NONE)
TOKEN(T_DOT_GLOBL, ".globl", TAFMT_NONE)
TOKEN(T_DOT_SIZE, ".size", TAFMT_NONE)
TOKEN(T_DOT_TEXT, ".text", TAFMT_NONE)
TOKEN(T_DOT_TYPE, ".type", TAFMT_NONE)
/* non-reserved symbols; T_SYMBOL MUST be the first token after the list of reserved symbols */
@@ -18,7 +19,9 @@ TOKEN(T_STRING, "<string>", TAFMT_STRING)
TOKEN(T_AT, "@", TAFMT_NONE)
TOKEN(T_COLON, ":", TAFMT_NONE)
TOKEN(T_COMMA, ",", TAFMT_NONE)
TOKEN(T_DOT, ".", TAFMT_NONE)
TOKEN(T_LPAREN, "(", TAFMT_NONE)
TOKEN(T_MINUS, "-", TAFMT_NONE)
TOKEN(T_RPAREN, ")", TAFMT_NONE)
/* synthetic symbols */
TOKEN(T_NEWLINE, "<newline>", TAFMT_NONE)
@@ -50,7 +53,6 @@ TOKEN(T_DOT_RODATA, ".rodata", TAFMT_NONE)
TOKEN(T_DOT_SECTION, ".section", TAFMT_NONE)
TOKEN(T_DOT_SET, ".set", TAFMT_NONE)
TOKEN(T_DOT_SHORT, ".short", TAFMT_NONE)
TOKEN(T_DOT_SIZE, ".size", TAFMT_NONE)
TOKEN(T_DOT_SUBSECTION, ".subsection", TAFMT_NONE)
TOKEN(T_DOT_SYMVER, ".symver", TAFMT_NONE)
TOKEN(T_DOT_WEAK, ".weak", TAFMT_NONE)
@@ -71,7 +73,6 @@ TOKEN(T_AND, "&", TAFMT_NONE)
TOKEN(T_CARET, "^", TAFMT_NONE)
TOKEN(T_BANG, "!", TAFMT_NONE)
TOKEN(T_PLUS, "+", TAFMT_NONE)
TOKEN(T_MINUS, "-", TAFMT_NONE)
TOKEN(T_EQ, "=", TAFMT_NONE)
TOKEN(T_EQEQ, "==", TAFMT_NONE)
TOKEN(T_NEQ, "!=", TAFMT_NONE)

View File

@@ -17,6 +17,7 @@ enum stmt_tag {
/* directives */
S_DOT_FILE,
S_DOT_GLOBL,
S_DOT_SIZE,
S_DOT_TEXT,
S_DOT_TYPE_FUNCTION,
/* non-directives */
@@ -31,7 +32,7 @@ struct stmt {
struct { /* S_DOT_FILE */
const char *text; /* XXX: should be pdp10_uint9_t* */
} string;
struct { /* S_DOT_GLOBL, S_LABEL, S_DOT_TYPE_FUNCTION */
struct { /* S_DOT_GLOBL, S_LABEL, S_DOT_SIZE, S_DOT_TYPE_FUNCTION */
const char *name;
} symbol;
struct { /* S_INSN */