mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-02-26 17:03:30 +00:00
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:
5
TODO
5
TODO
@@ -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)
|
||||
|
||||
26
as/input.c
26
as/input.c
@@ -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:
|
||||
|
||||
18
as/parse.c
18
as/parse.c
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
33
as/tunit.c
33
as/tunit.c
@@ -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.
|
||||
*/
|
||||
|
||||
25
as/tunit.h
25
as/tunit.h
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user