diff --git a/defs.h b/defs.h index 98650e8..9f40045 100644 --- a/defs.h +++ b/defs.h @@ -2240,6 +2240,9 @@ struct offset_table { /* stash of commonly-used offsets */ long mnt_namespace_nr_mounts; long mount_mnt_node; long log_caller_id; + long module_sect_attr_battr; + long bin_attribute_attr; + long attribute_name; }; struct size_table { /* stash of commonly-used sizes */ @@ -2911,8 +2914,9 @@ struct symbol_table_data { #define MODSECT_V1 (0x2000) #define MODSECT_V2 (0x4000) #define MODSECT_V3 (0x8000) -#define MODSECT_VMASK (MODSECT_V1|MODSECT_V2|MODSECT_V3) #define NO_STRIP (0x10000) +#define MODSECT_V4 (0x20000) +#define MODSECT_VMASK (MODSECT_V1|MODSECT_V2|MODSECT_V3|MODSECT_V4) #define NO_LINE_NUMBERS() ((st->flags & GDB_SYMS_PATCHED) && !(kt->flags2 & KASLR)) diff --git a/symbols.c b/symbols.c index cbc9ed1..19f7dd0 100644 --- a/symbols.c +++ b/symbols.c @@ -3812,6 +3812,8 @@ dump_symbol_table(void) fprintf(fp, "%sMODSECT_V2", others++ ? "|" : ""); if (st->flags & MODSECT_V3) fprintf(fp, "%sMODSECT_V3", others++ ? "|" : ""); + if (st->flags & MODSECT_V4) + fprintf(fp, "%sMODSECT_V4", others++ ? "|" : ""); if (st->flags & MODSECT_UNKNOWN) fprintf(fp, "%sMODSECT_UNKNOWN", others++ ? "|" : ""); if (st->flags & NO_STRIP) @@ -10233,6 +10235,7 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(module_sect_attrs_attrs)); fprintf(fp, " module_sect_attrs_nsections: %ld\n", OFFSET(module_sect_attrs_nsections)); + fprintf(fp, " module_sect_attr_battr: %ld\n", OFFSET(module_sect_attr_battr)); fprintf(fp, " module_sect_attr_mattr: %ld\n", OFFSET(module_sect_attr_mattr)); fprintf(fp, " module_sect_attr_name: %ld\n", @@ -10241,12 +10244,14 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(module_sect_attr_address)); fprintf(fp, " attribute_owner: %ld\n", OFFSET(attribute_owner)); + fprintf(fp, " attribute_name: %ld\n", OFFSET(attribute_name)); fprintf(fp, " module_sect_attr_attr: %ld\n", OFFSET(module_sect_attr_attr)); fprintf(fp, " module_sections_attrs: %ld\n", OFFSET(module_sections_attrs)); fprintf(fp, " module_attribute_attr: %ld\n", OFFSET(module_attribute_attr)); + fprintf(fp, " bin_attribute_attr: %ld\n", OFFSET(bin_attribute_attr)); fprintf(fp, " module_kallsyms_start: %ld\n", OFFSET(module_kallsyms_start)); @@ -13165,7 +13170,14 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) MEMBER_OFFSET_INIT(attribute_owner, "attribute", "owner"); - if (VALID_MEMBER(module_sect_attrs_attrs) && + /* Linux 5.8 and later */ + MEMBER_OFFSET_INIT(module_sect_attr_battr, "module_sect_attr", "battr"); + MEMBER_OFFSET_INIT(bin_attribute_attr, "bin_attribute", "attr"); + MEMBER_OFFSET_INIT(attribute_name, "attribute", "name"); + + if (VALID_MEMBER(module_sect_attr_battr)) + st->flags |= MODSECT_V4; + else if (VALID_MEMBER(module_sect_attrs_attrs) && VALID_MEMBER(module_sect_attr_mattr) && VALID_MEMBER(module_attribute_attr) && VALID_MEMBER(module_sect_attrs_nsections)) @@ -13185,7 +13197,7 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) (INVALID_MEMBER(attribute_owner) && (st->flags & (MODSECT_V1|MODSECT_V2))) || INVALID_MEMBER(module_sect_attrs) || - INVALID_MEMBER(module_sect_attr_name) || + (INVALID_MEMBER(module_sect_attr_name) && !(st->flags & MODSECT_V4)) || INVALID_MEMBER(module_sect_attr_address)) { if (CRASHDEBUG(1)) error(WARNING, @@ -13216,6 +13228,7 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) nsections = UNUSED; break; case MODSECT_V3: + case MODSECT_V4: array_entry = vaddr + OFFSET(module_sect_attrs_attrs); if (!readmem(vaddr + OFFSET(module_sect_attrs_nsections), KVADDR, &nsections, sizeof(int), @@ -13229,7 +13242,10 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) if (CRASHDEBUG(2)) fprintf(fp, "%s:\n", lm->mod_namelist); - name_type = MEMBER_TYPE("module_sect_attr", "name"); + name_type = TYPE_CODE_UNDEF; + if (!(st->flags & MODSECT_V4)) + name_type = MEMBER_TYPE("module_sect_attr", "name"); + req->buf = GETBUF(buflen = 1024); retval = FALSE; @@ -13245,6 +13261,10 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) attribute = array_entry + OFFSET(module_sect_attr_mattr) + OFFSET(module_attribute_attr); break; + case MODSECT_V4: + attribute = array_entry + OFFSET(module_sect_attr_battr) + + OFFSET(bin_attribute_attr); + break; } if (st->flags & (MODSECT_V1|MODSECT_V2)) @@ -13253,23 +13273,35 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) owner = UNUSED; address = array_entry + OFFSET(module_sect_attr_address); - switch (name_type) - { - case TYPE_CODE_ARRAY: - name = array_entry + OFFSET(module_sect_attr_name); - break; - case TYPE_CODE_PTR: - if (!readmem(array_entry + OFFSET(module_sect_attr_name), - KVADDR, &name, sizeof(void *), - "module_sect_attr.name", RETURN_ON_ERROR|QUIET)) { + + if (st->flags & MODSECT_V4) { + if (!readmem(array_entry + OFFSET(module_sect_attr_battr) + + OFFSET(bin_attribute_attr) + OFFSET(attribute_name), + KVADDR, &name, sizeof(void *), + "module_sect_attr.battr.attr.name", RETURN_ON_ERROR|QUIET)) { done = TRUE; retval = FALSE; continue; } - break; - default: - done = TRUE; - retval = FALSE; + } else { + switch (name_type) + { + case TYPE_CODE_ARRAY: + name = array_entry + OFFSET(module_sect_attr_name); + break; + case TYPE_CODE_PTR: + if (!readmem(array_entry + OFFSET(module_sect_attr_name), + KVADDR, &name, sizeof(void *), + "module_sect_attr.name", RETURN_ON_ERROR|QUIET)) { + done = TRUE; + retval = FALSE; + continue; + } + break; + default: + done = TRUE; + retval = FALSE; + } } if (CRASHDEBUG(2)) { @@ -13341,12 +13373,24 @@ add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req) } if (retval == FALSE) { + sprintf(buf, "add-symbol-file %s 0x%lx %s", + lm->mod_namelist, lm->mod_text_start, + pc->curcmd_flags & MOD_READNOW ? "-readnow" : ""); + len = strlen(req->buf); + while ((len + strlen(buf)) >= buflen) { + RESIZEBUF(req->buf, buflen, buflen * 2); + buflen *= 2; + } + shift_string_right(req->buf, strlen(buf)); + BCOPY(buf, req->buf, strlen(buf)); + /* if (CRASHDEBUG(1)) fprintf(fp, "%s: add_symbol_file_kallsyms failed\n", lm->mod_namelist); FREEBUF(req->buf); req->buf = NULL; return FALSE; + */ } /*