Future proofing core file format
* The Haiku specific notes contain a structure size field, now. * Change the type of the count and size fields in the Haiku specific notes to uint32 also for 64 bit ELF. The size field for a note is a uint32 anyway.
This commit is contained in:
parent
63a0065c83
commit
82185a52e2
@ -611,7 +611,7 @@ typedef struct {
|
||||
#define NT_IMAGES 0x696d6167 /* images */
|
||||
#define NT_THREADS 0x74687264 /* threads */
|
||||
|
||||
/* NT_TEAM: Elf32_Note_Team; char[] args */
|
||||
/* NT_TEAM: uint32 entrySize; Elf32_Note_Team; char[] args */
|
||||
typedef struct {
|
||||
int32 nt_id; /* team ID */
|
||||
int32 nt_uid; /* team owner ID */
|
||||
@ -620,7 +620,12 @@ typedef struct {
|
||||
|
||||
typedef Elf32_Note_Team Elf64_Note_Team;
|
||||
|
||||
/* NT_AREAS: uint32 count; Elf32_Note_Area_Entry[count]; char[] names */
|
||||
/* NT_AREAS:
|
||||
* uint32 count;
|
||||
* uint32 entrySize;
|
||||
* Elf32_Note_Area_Entry[count];
|
||||
* char[] names
|
||||
*/
|
||||
typedef struct {
|
||||
int32 na_id; /* area ID */
|
||||
uint32 na_lock; /* lock type (B_NO_LOCK, ...) */
|
||||
@ -630,7 +635,12 @@ typedef struct {
|
||||
uint32 na_ram_size; /* physical memory used */
|
||||
} Elf32_Note_Area_Entry;
|
||||
|
||||
/* NT_AREAS: uint64 count; Elf64_Note_Area_Entry[count]; char[] names */
|
||||
/* NT_AREAS:
|
||||
* uint32 count;
|
||||
* uint32 entrySize;
|
||||
* Elf64_Note_Area_Entry[count];
|
||||
* char[] names
|
||||
*/
|
||||
typedef struct {
|
||||
int32 na_id; /* area ID */
|
||||
uint32 na_lock; /* lock type (B_NO_LOCK, ...) */
|
||||
@ -641,7 +651,12 @@ typedef struct {
|
||||
uint64 na_ram_size; /* physical memory used */
|
||||
} Elf64_Note_Area_Entry;
|
||||
|
||||
/* NT_IMAGES: uint32 count; Elf32_Note_Image_Entry[count]; char[] names */
|
||||
/* NT_IMAGES:
|
||||
* uint32 count;
|
||||
* uint32 entrySize;
|
||||
* Elf32_Note_Image_Entry[count];
|
||||
* char[] names
|
||||
*/
|
||||
typedef struct {
|
||||
int32 ni_id; /* image ID */
|
||||
int32 ni_type; /* image type (B_APP_IMAGE, ...) */
|
||||
@ -655,7 +670,12 @@ typedef struct {
|
||||
uint32 ni_data_size; /* size of data segment */
|
||||
} Elf32_Note_Image_Entry;
|
||||
|
||||
/* NT_IMAGES: uint64 count; Elf64_Note_Image_Entry[count]; char[] names */
|
||||
/* NT_IMAGES:
|
||||
* uint32 count;
|
||||
* uint32 entrySize;
|
||||
* Elf64_Note_Image_Entry[count];
|
||||
* char[] names
|
||||
*/
|
||||
typedef struct {
|
||||
int32 ni_id; /* image ID */
|
||||
int32 ni_type; /* image type (B_APP_IMAGE, ...) */
|
||||
@ -672,6 +692,7 @@ typedef struct {
|
||||
|
||||
/* NT_THREADS:
|
||||
* uint32 count;
|
||||
* uint32 entrySize;
|
||||
* uint32 cpuStateSize;
|
||||
* {Elf32_Note_Thread_Entry, uint8[cpuStateSize] cpuState}[count];
|
||||
* char[] names
|
||||
@ -685,8 +706,9 @@ typedef struct {
|
||||
} Elf32_Note_Thread_Entry;
|
||||
|
||||
/* NT_THREADS:
|
||||
* uint64 count;
|
||||
* uint64 cpuStateSize;
|
||||
* uint32 count;
|
||||
* uint32 entrySize;
|
||||
* uint32 cpuStateSize;
|
||||
* {Elf64_Note_Thread_Entry, uint8[cpuStateSize] cpuState}[count];
|
||||
* char[] names
|
||||
*/
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <OS.h>
|
||||
|
||||
#include <AutoDeleter.h>
|
||||
@ -319,23 +321,34 @@ CoreFile::_ReadTeamNote(const void* data, uint32 dataSize)
|
||||
{
|
||||
typedef typename ElfClass::NoteTeam NoteTeam;
|
||||
|
||||
if (dataSize < sizeof(NoteTeam) + 1) {
|
||||
if (dataSize < sizeof(uint32)) {
|
||||
WARNING("Team note too short\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
const NoteTeam* note = (const NoteTeam*)data;
|
||||
uint32 entrySize = Get(*(const uint32*)data);
|
||||
data = (const uint32*)data + 1;
|
||||
dataSize -= sizeof(uint32);
|
||||
|
||||
if (entrySize == 0 || dataSize == 0 || dataSize - 1 < entrySize) {
|
||||
WARNING("Team note: too short or invalid entry size (%" B_PRIu32 ")\n",
|
||||
entrySize);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
NoteTeam note = {};
|
||||
_ReadEntry(data, dataSize, note, entrySize);
|
||||
|
||||
// check, if args are null-terminated
|
||||
const char* args = (const char*)(note + 1);
|
||||
size_t argsSize = dataSize - sizeof(NoteTeam);
|
||||
if (argsSize == 0 || args[argsSize - 1] != '\0') {
|
||||
const char* args = (const char*)data;
|
||||
size_t argsSize = dataSize;
|
||||
if (args[argsSize - 1] != '\0') {
|
||||
WARNING("Team note args not terminated\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
int32 id = Get(note->nt_id);
|
||||
int32 uid = Get(note->nt_uid);
|
||||
int32 gid = Get(note->nt_gid);
|
||||
int32 id = Get(note.nt_id);
|
||||
int32 uid = Get(note.nt_uid);
|
||||
int32 gid = Get(note.nt_gid);
|
||||
|
||||
BString copiedArgs(args);
|
||||
if (args[0] != '\0' && copiedArgs.Length() == 0)
|
||||
@ -350,29 +363,29 @@ template<typename ElfClass>
|
||||
status_t
|
||||
CoreFile::_ReadAreasNote(const void* data, uint32 dataSize)
|
||||
{
|
||||
const size_t addressSize = sizeof(typename ElfClass::Size);
|
||||
if (dataSize < addressSize) {
|
||||
if (dataSize < 2 * sizeof(uint32)) {
|
||||
WARNING("Areas note too short\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
uint64 areaCount = Get(*(const typename ElfClass::Size*)data);
|
||||
uint32 areaCount = _ReadValue<uint32>(data, dataSize);
|
||||
uint32 entrySize = _ReadValue<uint32>(data, dataSize);
|
||||
|
||||
typedef typename ElfClass::NoteAreaEntry Entry;
|
||||
const Entry* table = (Entry*)((const uint8*)data + addressSize);
|
||||
dataSize -= addressSize;
|
||||
|
||||
if (areaCount == 0)
|
||||
return B_OK;
|
||||
|
||||
// check area count
|
||||
if (areaCount > dataSize || areaCount * sizeof(Entry) >= dataSize) {
|
||||
WARNING("Areas note too short for area count\n");
|
||||
// check entry size and area count
|
||||
if (entrySize == 0 || dataSize == 0 || areaCount > dataSize
|
||||
|| dataSize - 1 < entrySize || areaCount * entrySize >= dataSize) {
|
||||
WARNING("Areas note: too short or invalid entry size (%" B_PRIu32 ")\n",
|
||||
entrySize);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
// check, if strings are null-terminated
|
||||
const char* strings = (const char*)(table + areaCount);
|
||||
size_t stringsSize = dataSize - areaCount * sizeof(Entry);
|
||||
const char* strings = (const char*)data + areaCount * entrySize;
|
||||
size_t stringsSize = dataSize - areaCount * entrySize;
|
||||
if (stringsSize == 0 || strings[stringsSize - 1] != '\0') {
|
||||
WARNING("Areas note strings not terminated\n");
|
||||
return B_BAD_DATA;
|
||||
@ -380,8 +393,8 @@ CoreFile::_ReadAreasNote(const void* data, uint32 dataSize)
|
||||
|
||||
for (uint64 i = 0; i < areaCount; i++) {
|
||||
// get entry values
|
||||
Entry entry;
|
||||
memcpy(&entry, table, sizeof(entry));
|
||||
Entry entry = {};
|
||||
_ReadEntry(data, dataSize, entry, entrySize);
|
||||
|
||||
int32 id = Get(entry.na_id);
|
||||
uint64 baseAddress = Get(entry.na_base);
|
||||
@ -413,8 +426,6 @@ CoreFile::_ReadAreasNote(const void* data, uint32 dataSize)
|
||||
delete area;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
table++;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -425,29 +436,29 @@ template<typename ElfClass>
|
||||
status_t
|
||||
CoreFile::_ReadImagesNote(const void* data, uint32 dataSize)
|
||||
{
|
||||
const size_t addressSize = sizeof(typename ElfClass::Size);
|
||||
if (dataSize < addressSize) {
|
||||
if (dataSize < 2 * sizeof(uint32)) {
|
||||
WARNING("Images note too short\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
uint64 imageCount = Get(*(const typename ElfClass::Size*)data);
|
||||
uint32 imageCount = _ReadValue<uint32>(data, dataSize);
|
||||
uint32 entrySize = _ReadValue<uint32>(data, dataSize);
|
||||
|
||||
typedef typename ElfClass::NoteImageEntry Entry;
|
||||
const Entry* table = (Entry*)((const uint8*)data + addressSize);
|
||||
dataSize -= addressSize;
|
||||
|
||||
if (imageCount == 0)
|
||||
return B_OK;
|
||||
|
||||
// check image count
|
||||
if (imageCount > dataSize || imageCount * sizeof(Entry) >= dataSize) {
|
||||
WARNING("Images note too short for image count\n");
|
||||
// check entry size and image count
|
||||
if (entrySize == 0 || dataSize == 0 || imageCount > dataSize
|
||||
|| dataSize - 1 < entrySize || imageCount * entrySize >= dataSize) {
|
||||
WARNING("Images note: too short or invalid entry size (%" B_PRIu32
|
||||
")\n", entrySize);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
// check, if strings are null-terminated
|
||||
const char* strings = (const char*)(table + imageCount);
|
||||
size_t stringsSize = dataSize - imageCount * sizeof(Entry);
|
||||
const char* strings = (const char*)data + imageCount * entrySize;
|
||||
size_t stringsSize = dataSize - imageCount * entrySize;
|
||||
if (stringsSize == 0 || strings[stringsSize - 1] != '\0') {
|
||||
WARNING("Images note strings not terminated\n");
|
||||
return B_BAD_DATA;
|
||||
@ -455,8 +466,8 @@ CoreFile::_ReadImagesNote(const void* data, uint32 dataSize)
|
||||
|
||||
for (uint64 i = 0; i < imageCount; i++) {
|
||||
// get entry values
|
||||
Entry entry;
|
||||
memcpy(&entry, table, sizeof(entry));
|
||||
Entry entry = {};
|
||||
_ReadEntry(data, dataSize, entry, entrySize);
|
||||
|
||||
int32 id = Get(entry.ni_id);
|
||||
int32 type = Get(entry.ni_type);
|
||||
@ -494,8 +505,6 @@ CoreFile::_ReadImagesNote(const void* data, uint32 dataSize)
|
||||
delete image;
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
table++;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -506,40 +515,39 @@ template<typename ElfClass>
|
||||
status_t
|
||||
CoreFile::_ReadThreadsNote(const void* data, uint32 dataSize)
|
||||
{
|
||||
const size_t addressSize = sizeof(typename ElfClass::Size);
|
||||
if (dataSize < 2 * addressSize) {
|
||||
if (dataSize < 3 * sizeof(uint32)) {
|
||||
WARNING("Threads note too short\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
const typename ElfClass::Size* header
|
||||
= (const typename ElfClass::Size*)data;
|
||||
uint64 threadCount = Get(header[0]);
|
||||
uint64 cpuStateSize = Get(header[1]);
|
||||
uint32 threadCount = _ReadValue<uint32>(data, dataSize);
|
||||
uint32 entrySize = _ReadValue<uint32>(data, dataSize);
|
||||
uint32 cpuStateSize = _ReadValue<uint32>(data, dataSize);
|
||||
|
||||
if (cpuStateSize > 1024 * 1024) {
|
||||
WARNING("Threads note: unreasonable CPU state size: %" B_PRIu64 "\n",
|
||||
WARNING("Threads note: unreasonable CPU state size: %" B_PRIu32 "\n",
|
||||
cpuStateSize);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
typedef typename ElfClass::NoteThreadEntry Entry;
|
||||
const uint8* table = (const uint8*)(header + 2);
|
||||
dataSize -= 2 * addressSize;
|
||||
|
||||
size_t totalEntrySize = sizeof(Entry) + (size_t)cpuStateSize;
|
||||
|
||||
// check thread count
|
||||
if (threadCount > dataSize || threadCount * totalEntrySize >= dataSize) {
|
||||
WARNING("Threads note too short for thread count\n");
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
if (threadCount == 0)
|
||||
return B_OK;
|
||||
|
||||
size_t totalEntrySize = entrySize + cpuStateSize;
|
||||
|
||||
// check entry size and thread count
|
||||
if (entrySize == 0 || dataSize == 0 || threadCount > dataSize
|
||||
|| entrySize > dataSize || cpuStateSize > dataSize
|
||||
|| dataSize - 1 < totalEntrySize
|
||||
|| threadCount * totalEntrySize >= dataSize) {
|
||||
WARNING("Threads note: too short or invalid entry size (%" B_PRIu32
|
||||
")\n", entrySize);
|
||||
return B_BAD_DATA;
|
||||
}
|
||||
|
||||
// check, if strings are null-terminated
|
||||
const char* strings = (const char*)(table + threadCount * totalEntrySize);
|
||||
const char* strings = (const char*)data + threadCount * totalEntrySize;
|
||||
size_t stringsSize = dataSize - threadCount * totalEntrySize;
|
||||
if (stringsSize == 0 || strings[stringsSize - 1] != '\0') {
|
||||
WARNING("Threads note strings not terminated\n");
|
||||
@ -548,8 +556,8 @@ CoreFile::_ReadThreadsNote(const void* data, uint32 dataSize)
|
||||
|
||||
for (uint64 i = 0; i < threadCount; i++) {
|
||||
// get entry values
|
||||
Entry entry;
|
||||
memcpy(&entry, table, sizeof(entry));
|
||||
Entry entry = {};
|
||||
_ReadEntry(data, dataSize, entry, entrySize);
|
||||
|
||||
int32 id = Get(entry.nth_id);
|
||||
int32 state = Get(entry.nth_state);
|
||||
@ -581,11 +589,9 @@ CoreFile::_ReadThreadsNote(const void* data, uint32 dataSize)
|
||||
}
|
||||
|
||||
// get CPU state
|
||||
const void* cpuState = table + sizeof(Entry);
|
||||
if (!thread->SetCpuState(cpuState, cpuStateSize))
|
||||
if (!thread->SetCpuState(data, cpuStateSize))
|
||||
return B_NO_MEMORY;
|
||||
|
||||
table += totalEntrySize;
|
||||
_Advance(data, dataSize, cpuStateSize);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@ -622,3 +628,29 @@ CoreFile::_FindAreaSegment(uint64 address) const
|
||||
}
|
||||
|
||||
|
||||
template<typename Type>
|
||||
Type
|
||||
CoreFile::_ReadValue(const void*& data, uint32& dataSize)
|
||||
{
|
||||
Type value = Get(*(const Type*)data);
|
||||
_Advance(data, dataSize, sizeof(Type));
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
template<typename Entry>
|
||||
void
|
||||
CoreFile::_ReadEntry(const void*& data, uint32& dataSize, Entry& entry,
|
||||
size_t entrySize)
|
||||
{
|
||||
memcpy(&entry, data, std::min(sizeof(entry), entrySize));
|
||||
_Advance(data, dataSize, entrySize);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CoreFile::_Advance(const void*& data, uint32& dataSize, size_t by)
|
||||
{
|
||||
data = (const uint8*)data + by;
|
||||
dataSize -= by;
|
||||
}
|
||||
|
@ -179,6 +179,14 @@ private:
|
||||
CoreFileAreaInfo* _FindArea(uint64 address) const;
|
||||
ElfSegment* _FindAreaSegment(uint64 address) const;
|
||||
|
||||
template<typename Type>
|
||||
Type _ReadValue(const void*& data, uint32& dataSize);
|
||||
template<typename Entry>
|
||||
void _ReadEntry(const void*& data, uint32& dataSize,
|
||||
Entry& entry, size_t entrySize);
|
||||
void _Advance(const void*& data, uint32& dataSize,
|
||||
size_t by);
|
||||
|
||||
template<typename Value>
|
||||
Value Get(const Value& value) const
|
||||
{ return fElfFile.Get(value); }
|
||||
|
@ -1134,7 +1134,8 @@ private:
|
||||
note.nt_id = fTeamInfo.team;
|
||||
note.nt_uid = fTeamInfo.uid;
|
||||
note.nt_gid = fTeamInfo.gid;
|
||||
writer.Write(¬e, sizeof(note));
|
||||
writer.Write((uint32)sizeof(note));
|
||||
writer.Write(note);
|
||||
|
||||
// write args
|
||||
const char* args = fTeamInfo.args;
|
||||
@ -1214,7 +1215,8 @@ private:
|
||||
void _WriteAreasNote(Writer& writer)
|
||||
{
|
||||
// area count
|
||||
writer.Write(fAreaCount);
|
||||
writer.Write((uint32)fAreaCount);
|
||||
writer.Write((uint32)sizeof(elf_note_area_entry));
|
||||
|
||||
// write table
|
||||
for (AreaInfoList::Iterator it = fAreaInfos.GetIterator();
|
||||
@ -1227,7 +1229,7 @@ private:
|
||||
entry.na_base = areaInfo->Base();
|
||||
entry.na_size = areaInfo->Size();
|
||||
entry.na_ram_size = areaInfo->RamSize();
|
||||
writer.Write(&entry, sizeof(entry));
|
||||
writer.Write(entry);
|
||||
}
|
||||
|
||||
// write strings
|
||||
@ -1261,7 +1263,8 @@ private:
|
||||
void _WriteImagesNote(Writer& writer)
|
||||
{
|
||||
// image count
|
||||
writer.Write(fImageCount);
|
||||
writer.Write((uint32)fImageCount);
|
||||
writer.Write((uint32)sizeof(elf_note_image_entry));
|
||||
|
||||
// write table
|
||||
for (ImageInfoList::Iterator it = fImageInfos.GetIterator();
|
||||
@ -1278,7 +1281,7 @@ private:
|
||||
entry.ni_text_size = imageInfo->TextSize();
|
||||
entry.ni_data_base = imageInfo->DataBase();
|
||||
entry.ni_data_size = imageInfo->DataSize();
|
||||
writer.Write(&entry, sizeof(entry));
|
||||
writer.Write(entry);
|
||||
}
|
||||
|
||||
// write strings
|
||||
@ -1312,8 +1315,9 @@ private:
|
||||
void _WriteThreadsNote(Writer& writer)
|
||||
{
|
||||
// thread count and size of CPU state
|
||||
writer.Write(fThreadCount);
|
||||
writer.Write(sizeof(debug_cpu_state));
|
||||
writer.Write((uint32)fThreadCount);
|
||||
writer.Write((uint32)sizeof(elf_note_thread_entry));
|
||||
writer.Write((uint32)sizeof(debug_cpu_state));
|
||||
|
||||
// write table
|
||||
for (ThreadStateList::Iterator it = fThreadStates.GetIterator();
|
||||
|
Loading…
Reference in New Issue
Block a user