debug: invoke dfmt->linenum when the segment number changes

If the segment number changes, we also need to invoke dfmt->linenum(),
as a .nolist macro may end up emitting to more than one section.

This also adds the source location explicitly to the output data
structure; the cost for that is minimal, and will enable a more
sophisticated debug backend to receive the entire data structure in
the future.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2020-07-09 20:03:55 -07:00
parent 771e714c71
commit 2f171ddeec
3 changed files with 26 additions and 11 deletions

View File

@ -341,8 +341,10 @@ static void warn_overflow_out(int64_t data, int size, enum out_sign sign)
*/
static void out(struct out_data *data)
{
static int32_t lineno = 0; /* static!!! */
static const char *lnfname = NULL;
static struct last_debug_info {
struct src_location where;
int32_t segment;
} dbg;
union {
uint8_t b[8];
uint64_t q;
@ -398,16 +400,16 @@ static void out(struct out_data *data)
}
/*
* this call to src_get determines when we call the
* debug-format-specific "linenum" function
* it updates lineno and lnfname to the current values
* returning 0 if "same as last time", -2 if lnfname
* changed, and the amount by which lineno changed,
* if it did. thus, these variables must be static
* If the source location or output segment has changed,
* let the debug backend know.
*/
if (src_get(&lineno, &lnfname))
dfmt->linenum(lnfname, lineno, data->segment);
data->where = src_where();
if (!src_location_same(data->where, dbg.where) |
(data->segment != dbg.segment)) {
dbg.where = data->where;
dbg.segment = data->segment;
dfmt->linenum(dbg.where.filename, dbg.where.lineno, data->segment);
}
if (asize > amax) {
if (data->type == OUT_RELADDR || data->sign == OUT_SIGNED) {

View File

@ -43,6 +43,18 @@ struct src_location {
const char *filename;
int32_t lineno;
};
/*
* Comparing the *pointer value* of filenames is valid, because the
* filename hash system guarantees that each unique filename string is
* permanently allocated in exactly one location.
*/
static inline bool
src_location_same(struct src_location here, struct src_location there)
{
return here.filename == there.filename && here.lineno == there.lineno;
}
struct src_location_stack {
struct src_location l;
struct src_location_stack *up, *down;

View File

@ -137,6 +137,7 @@ struct out_data {
int32_t tsegment; /* Target segment for relocation */
int32_t twrt; /* Relocation with respect to */
int64_t relbase; /* Relative base for OUT_RELADDR */
struct src_location where; /* Source file and line */
};
/*