as: add support for .ident directives

- token.def: enable T_DOT_IDENT
- tunit.h: add S_DOT_IDENT and make it share attributes with S_DOT_FILE,
  describe available section types, add tunit_strtab_section_enter(),
  rearrange declarations
- tunit.c: implement tunit_strtab_section_enter()
- parse.c: generalize .file parser, use it also for .ident
- input.c: handle S_DOT_IDENT, lookup or create .comment strtab section,
  append given string literal to that section
This commit is contained in:
Mikael Pettersson
2015-05-01 14:14:38 +02:00
parent a5a68a70b7
commit 47502d2bb7
6 changed files with 96 additions and 13 deletions

5
TODO
View File

@@ -43,9 +43,8 @@ Tools:
- readelf: add support for relocs
- readelf: add support for program headers
- as:
* support .ident:
+ have .ident append string to .comment strtab
+ finalize .comment strtab before output()
* tunit_{strtab_,}section_enter() should be generalized and merged
* what happens if user defines .comment as say text, and later enters .ident?
* add support for named sections
* add support for sub-sections
* add support for data directives (.word, .asciz, etc)

View File

@@ -87,6 +87,30 @@ static int do_dot_globl(struct scan_state *scan_state, struct tunit *tunit, stru
return 0;
}
static int do_dot_ident(struct scan_state *scan_state, struct tunit *tunit, struct stmt *stmt)
{
struct strtab *strtab;
strtab = tunit_strtab_section_enter(tunit, ".comment");
if (!strtab)
return -1;
if (strtab->section.sh_type == SHT_NULL) {
/* The ELF specification doesn't specify attribute values for .comment
* sections, apart from sh_type, but GNU binutils formats them as string
* tables with the following attribute values.
*/
strtab->section.sh_type = SHT_PROGBITS;
strtab->section.sh_flags = SHF_MERGE | SHF_STRINGS;
strtab->section.sh_entsize = 1;
strtab->section.sh_addralign = 1;
}
(void)strtab_enter(tunit, strtab, stmt->u.string.text);
return 0;
}
static int do_dot_size(struct scan_state *scan_state, struct tunit *tunit, struct stmt *stmt)
{
struct symbol *symbol;
@@ -198,6 +222,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_IDENT:
return do_dot_ident(scan_state, tunit, stmt);
case S_DOT_SIZE:
return do_dot_size(scan_state, tunit, stmt);
case S_DOT_TEXT:

View File

@@ -35,7 +35,7 @@ static int error(struct scan_state *scan_state, const char *msg, enum token toke
return -1;
}
static int parse_dot_file(struct scan_state *scan_state, struct stmt *stmt)
static int parse_dot_file_or_ident(struct scan_state *scan_state, struct stmt *stmt, enum stmt_tag tag, const char *errmsg)
{
enum token token;
union token_attribute token_attr;
@@ -45,11 +45,21 @@ static int parse_dot_file(struct scan_state *scan_state, struct stmt *stmt)
stmt->u.string.text = token_attr.text;
token = scan_token(scan_state, &token_attr);
if (token == T_NEWLINE) {
stmt->tag = S_DOT_FILE;
stmt->tag = tag;
return 1;
}
}
return error(scan_state, "junk after .file directive", token, &token_attr);
return error(scan_state, errmsg, token, &token_attr);
}
static int parse_dot_file(struct scan_state *scan_state, struct stmt *stmt)
{
return parse_dot_file_or_ident(scan_state, stmt, S_DOT_FILE, "junk after .file directive");
}
static int parse_dot_ident(struct scan_state *scan_state, struct stmt *stmt)
{
return parse_dot_file_or_ident(scan_state, stmt, S_DOT_IDENT, "junk after .ident directive");
}
static int parse_dot_globl(struct scan_state *scan_state, struct stmt *stmt)
@@ -428,6 +438,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_IDENT:
return parse_dot_ident(scan_state, stmt);
case T_DOT_SIZE:
return parse_dot_size(scan_state, stmt);
case T_DOT_TEXT:

View File

@@ -25,6 +25,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_IDENT, ".ident", TAFMT_NONE)
TOKEN(T_DOT_SIZE, ".size", TAFMT_NONE)
TOKEN(T_DOT_TEXT, ".text", TAFMT_NONE)
TOKEN(T_DOT_TYPE, ".type", TAFMT_NONE)
@@ -57,7 +58,6 @@ TOKEN(T_DOT_BYTE, ".byte", TAFMT_NONE)
TOKEN(T_DOT_COMM, ".comm", TAFMT_NONE)
TOKEN(T_DOT_DATA, ".data", TAFMT_NONE)
TOKEN(T_DOT_HIDDEN, ".hidden", TAFMT_NONE)
TOKEN(T_DOT_IDENT, ".ident", TAFMT_NONE)
TOKEN(T_DOT_INTERNAL, ".internal", TAFMT_NONE)
TOKEN(T_DOT_LOCAL, ".local", TAFMT_NONE)
TOKEN(T_DOT_LONG, ".long", TAFMT_NONE)

View File

@@ -190,6 +190,39 @@ void strtab_init(struct strtab *strtab, const char *name)
strtab->head = NULL;
}
static struct strtab *strtab_from_hashnode(const struct hashnode *hashnode)
{
return hashnode ? container_of(hashnode, struct strtab, section.hashnode) : NULL;
}
/* XXX: generalize and merge with tunit_section_enter() */
struct strtab *tunit_strtab_section_enter(struct tunit *tunit, const char *name)
{
uintptr_t hashval;
struct strtab *strtab;
hashval = string_hash(name);
strtab = strtab_from_hashnode(hashtab_lookup(&tunit->sections, hashval, name));
if (strtab)
return strtab;
strtab = malloc(sizeof *strtab);
if (!strtab) {
fprintf(stderr, "%s: %s: malloc(%zu) failed: %s\n", tunit->progname, __FUNCTION__, sizeof *strtab, strerror(errno));
return NULL;
}
strtab_init(strtab, name);
/* XXX: undo stuff strtab_init() did which breaks .ident */
strtab->section.sh_type = SHT_NULL;
strtab->section.hashnode.hashval = hashval;
if (hashtab_insert(&tunit->sections, &strtab->section.hashnode) < 0)
return NULL;
return strtab;
}
/*
* Symbols hash table.
*/

View File

@@ -35,6 +35,7 @@ enum stmt_tag {
/* directives */
S_DOT_FILE,
S_DOT_GLOBL,
S_DOT_IDENT,
S_DOT_SIZE,
S_DOT_TEXT,
S_DOT_TYPE_FUNCTION,
@@ -47,7 +48,7 @@ struct stmt {
struct stmt *next;
enum stmt_tag tag;
union {
struct { /* S_DOT_FILE */
struct { /* S_DOT_FILE, S_DOT_IDENT */
const char *text; /* XXX: should be pdp10_uint9_t* */
} string;
struct { /* S_DOT_GLOBL, S_LABEL, S_DOT_SIZE, S_DOT_TYPE_FUNCTION */
@@ -63,6 +64,16 @@ struct stmt {
} u;
};
/*
* Sections.
*
* There are several kinds of sections:
* - generic sections with an image array
* these contain instructions or initialized data
* - strtab sections
* these contain a strtab and a specialised ->output() method
*/
struct section {
struct hashnode hashnode;
const char *name;
@@ -80,8 +91,6 @@ struct section {
Elf36_Word sh_entsize; /* assigned during output */
};
void section_init(struct section *section, const char *name);
struct strtab_entry {
struct strtab_entry *next;
const char *string;
@@ -119,13 +128,17 @@ struct tunit {
int tunit_init(struct tunit *tunit, const char *progname);
void tunit_fini(struct tunit *tunit);
void section_init(struct section *section, const char *name);
struct section *tunit_section_enter(struct tunit *tunit, const char *name);
struct strtab *tunit_strtab_section_enter(struct tunit *tunit, const char *name);
void strtab_init(struct strtab *strtab, const char *name);
pdp10_uint36_t strtab_enter(struct tunit *tunit, struct strtab *strtab, const char *name);
struct symbol *tunit_symbol_lookup(struct tunit *tunit, const char *name);
struct symbol *tunit_symbol_enter(struct tunit *tunit, const char *name);
pdp10_uint36_t strtab_enter(struct tunit *tunit, struct strtab *strtab, const char *name);
void strtab_init(struct strtab *strtab, const char *name);
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.