File indexing completed on 2024-05-12 05:43:31

0001 /*
0002     Copyright (C) 2015 Volker Krause <vkrause@kde.org>
0003 
0004     This program is free software; you can redistribute it and/or modify it
0005     under the terms of the GNU Library General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or (at your
0007     option) any later version.
0008 
0009     This program is distributed in the hope that it will be useful, but WITHOUT
0010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0012     License for more details.
0013 
0014     You should have received a copy of the GNU General Public License
0015     along with this program.  If not, see <https://www.gnu.org/licenses/>.
0016 */
0017 
0018 #include "notesectionprinter.h"
0019 #include <elf/elfnoteentry.h>
0020 
0021 #include <QByteArray>
0022 
0023 #include <elf.h>
0024 
0025 #include <cassert>
0026 
0027 struct NoteType {
0028     uint32_t type;
0029     const char* name;
0030 };
0031 
0032 #define NT(type) { NT_ ## type, #type }
0033 
0034 static const NoteType note_types[] {
0035     NT(GNU_ABI_TAG),
0036     NT(GNU_HWCAP),
0037     NT(GNU_BUILD_ID),
0038     NT(GNU_GOLD_VERSION)
0039 };
0040 
0041 #undef NT
0042 
0043 static const int note_types_size = sizeof(note_types) / sizeof(NoteType);
0044 
0045 #ifdef Q_OS_FREEBSD
0046 // FreeBSD elf-common.h has no ELF_NOTE_OS_* and those are strings, anyway
0047 
0048 static const NoteType os_types[] {
0049     { 0, ELF_NOTE_FREEBSD },
0050     // TODO: is that a sensible value?
0051     // TODO: there's also NETBSD, SOLARIS and GNU
0052 };
0053 
0054 
0055 #else
0056 #define OS(type) { ELF_NOTE_OS_ ## type, #type }
0057 
0058 static const NoteType os_types[] {
0059     OS(LINUX),
0060     OS(GNU),
0061     OS(SOLARIS2),
0062     OS(FREEBSD)
0063 };
0064 
0065 #undef OS
0066 #endif
0067 
0068 static const int os_types_size = sizeof(note_types) / sizeof(NoteType);
0069 
0070 static const NoteType* noteType(uint32_t type, const NoteType *table, int size)
0071 {
0072     for (int i = 0; i < size; ++i) {
0073         if (table[i].type == type)
0074             return &table[i];
0075     }
0076     return nullptr;
0077 }
0078 
0079 const char* NoteSectionPrinter::typeDisplayString(ElfNoteEntry* entry)
0080 {
0081     if (!entry->isGNUVendorNote())
0082         return entry->name();
0083 
0084     const auto nt = noteType(entry->type(), note_types, note_types_size);
0085     if (!nt)
0086         return entry->name();
0087     return nt->name;
0088 }
0089 
0090 QByteArray NoteSectionPrinter::abi(ElfNoteEntry* entry)
0091 {
0092     assert(entry->isGNUVendorNote());
0093     assert(entry->type() == NT_GNU_ABI_TAG);
0094     assert(entry->descriptionSize() >= 16);
0095     QByteArray r;
0096 
0097     struct ABIDesc {
0098         uint32_t os;
0099         uint32_t major;
0100         uint32_t minor;
0101         uint32_t patch;
0102     };
0103     const ABIDesc *abiDesc = reinterpret_cast<const ABIDesc*>(entry->descriptionData());
0104 
0105     const auto osType = noteType(abiDesc->os, os_types, os_types_size);
0106     if (osType) {
0107         r += osType->name;
0108     } else {
0109         r += "Unknown OS";
0110     }
0111 
0112     r += ' ';
0113     r += QByteArray::number(abiDesc->major);
0114     r += '.';
0115     r += QByteArray::number(abiDesc->minor);
0116     r += '.';
0117     r += QByteArray::number(abiDesc->patch);
0118 
0119     return r;
0120 }