Menu

#616 Create helper function in libelftc to get name of note type

RELEASE_1_0
accepted
None
libelftc
2023-05-06
2023-04-22
No

Moved note type name methods of readelf to common place to reuse the same logic in readelf and elfdump, the only difference is that we return NULL instead of an unknown type message as readelf and elfdump return different unknown type messages, thus idea in the next patches integrate this new logic to elfdump and readelf and we will print unkown message if elftc_get_note_type_namefunction returns NULL.

readelf:

static const char *
note_type_unknown(unsigned int nt)
{
    static char s_nt[32];

    snprintf(s_nt, sizeof(s_nt),
        nt >= 0x100 ? "<unknown: 0x%x>" : "<unknown: %u>", nt);
    return (s_nt);
}

ref: https://sourceforge.net/p/elftoolchain/code/HEAD/tree/trunk/readelf/readelf.c#l1232

static void
elf_print_note(Elf32_Ehdr *e, void *sh)
{
        // ...
        if (type < nitems(nt_types) && nt_types[type] != NULL)
            nt_type = nt_types[type];
        else
            nt_type = "Unknown type";
}

ref: https://github.com/freebsd/freebsd-src/blob/main/usr.bin/elfdump/elfdump.c#L1094

1 Attachments

Discussion

  • Joseph Koshy

    Joseph Koshy - 2023-04-23

    An observation about the (c) lines in the patch: if the code was largely copied from elsewhere the (c) lines in the new file should mention the authors of the original source code.

     
  • Mykola Hohsadze

    Mykola Hohsadze - 2023-04-23

    added original author to the new file

     
  • Joseph Koshy

    Joseph Koshy - 2023-04-27

    Since we are introducing a new API, we would need a manual page and tests to accompany the new function. I will add these when incorporating this patch.

     
    👍
    1
  • Joseph Koshy

    Joseph Koshy - 2023-04-27
    • status: new --> accepted
     
  • Joseph Koshy

    Joseph Koshy - 2023-04-29

    Looking at where the function would be used it looks like a prototype like const char * elfc_get_note_type(const Elf_Note *note, size_t max_offset) may be more convenient to use.

    With such a function we could hide the special-casing in https://sourceforge.net/p/elftoolchain/code/HEAD/tree/trunk/readelf/readelf.c#l3671, and have consistent behavior from elfdump and readelf.

     
  • Mykola Hohsadze

    Mykola Hohsadze - 2023-05-06

    I didn't understand idea of size_t max_offset in elfc_get_note_type, the values that we should use to get type name of note are object type of file and note section info.

    I would separate to two functions elftc_get_note_name and elftc_get_note_type_name.

    elftc_get_note_name we will know if this note name is invalid and we will return NULL and handle in elfdump and readelf, also we will correct special case CORE in function.

    In readelf we know that we print <invalid> https://sourceforge.net/p/elftoolchain/code/HEAD/tree/trunk/readelf/readelf.c#l3684
    but what should be in elfdump?

    The same case n_namesz == 0 should we return ""? It is correct for readelf, but what we want to see in elfdump?

    Is it ok if we not see the note name:

    note (.note.my_section):
            10 (Unknown Type)
    

    or should we type something like this:

    note (.note.my_section):
            None 10 (Unknown Type)
    
    const char *
    elftc_get_note_name(const Elf_Note *note)
    {
            /*
             * The name field is required to be nul-terminated, and
             * n_namesz includes the terminating nul in observed
             * implementations (contrary to the ELF-64 spec). A special
             * case is needed for cores generated by some older Linux
             * versions, which write a note named "CORE" without a nul
             * terminator and n_namesz = 4.
             */
            if (note->n_namesz == 0)
                    return "";
            else if (note->n_namesz == 4 && strncmp(n_name, "CORE", 4) == 0)
                    return "CORE";
            else if (strnlen(n_name, note->n_namesz) >= note->n_namesz)
                    return NULL;
            return (char *) (uintptr_t) note + sizeof(Elf_Note);
    }
    
    /*
     * Gets name of note type by note section info and object file type.
     */
    const char *
    elftc_get_note_type_name(const char *n_name, unsigned int n_type,
        unsigned int e_type)
    {
            if ((strcmp(n_name, "CORE") == 0 || strcmp(n_name, "LINUX") == 0) &&
                e_type == ET_CORE)
                    return note_type_linux_core(n_type);
            else if (strcmp(n_name, "FreeBSD") == 0)
                    if (e_type == ET_CORE)
                            return note_type_freebsd_core(n_type);
                    else
                            return note_type_freebsd(n_type);
            else if (strcmp(n_name, "GNU") == 0 && e_type != ET_CORE)
                    return note_type_gnu(n_type);
            else if (strcmp(n_name, "NetBSD") == 0 && e_type != ET_CORE)
                    return note_type_netbsd(n_type);
            else if (strcmp(n_name, "OpenBSD") == 0 && e_type != ET_CORE)
                    return note_type_openbsd(n_type);
            else if (strcmp(n_name, "Xen") == 0 && e_type != ET_CORE)
                    return note_type_xen(n_type);
            return NULL;
    }
    

    What do you think?

     

Log in to post a comment.