C: Correctly using a memory address for an array of structs?
Posted: Sat Apr 27, 2024 6:55 pm
Hi,
I've been writing a hobby OS on aarch64 and so far have only used the stack. I've reached the point where I want to implement dynamic memory and I've realised by understanding of C pointers/memory is extremely poor (it seems), so I've been trying to write several barebones practice routines to learn a bit more. My main background is usually a non-freestanding C++ environment or JavaScript.
This is what I'm trying to do:
A. I have a page aligned 4K page set by the linker.
B. I want to use this page to store 32 128-byte sized records at this address.
C. The definition of a record is:
D. I am trying something like this in the C file:
E. My memcpy, strlen and log/printf functions are fine, and work as expected in other contexts / uses. This is in a barebones freestanding C enviroment so accessing memory at these addresses is fine, nothing else is overwriting the memory etc.
F. My output is this:
So my questions are:
1. What exactly am I doing wrong, mixing up pointer dereferencing / not dereferencing correctly?
2. What is the correct way to use an address provided by the linker as the base for an array of structs?
3. Is there is correct method of doing this where I have a typed array (so record_t records[] instead of a void*)?
4. The memory offset is correct, because size = 0x80, and the second entry (1) is being placed at 0x90080? Am I mixing up bytes / hex / decimal?
5. What is the correct way to do this overall?
Thank you kindly.
I've been writing a hobby OS on aarch64 and so far have only used the stack. I've reached the point where I want to implement dynamic memory and I've realised by understanding of C pointers/memory is extremely poor (it seems), so I've been trying to write several barebones practice routines to learn a bit more. My main background is usually a non-freestanding C++ environment or JavaScript.
This is what I'm trying to do:
A. I have a page aligned 4K page set by the linker.
B. I want to use this page to store 32 128-byte sized records at this address.
C. The definition of a record is:
Code: Select all
struct {
char [112] name;
uint64_t start;
uint64_t end;
}
Code: Select all
extern volatile uint64_t _address_from_linker;
struct __attribute__((__packed__)) record {
char name[112];
uint64_t start;
uint64_t end;
};
typedef struct record record_t;
void* m_Entries;
uint8_t m_EntriesCount = 0;
void records_init() {
m_Entries = &_address_from_linker;
m_EntriesCount = 0;
size_t record_size = sizeof(record_t);
log("record size: 0x%X, %d", record_size, record_size);
log("records base addr: %p", m_Entries);
records_add("Test1", 0x1000, 0x1FFFF);
records_add("Test2", 0x2000, 0x2FFFF);
}
void records_add(const char* name, uint64_t start, uint64_t end) {
record_t* rec = (record_t*)(m_Entries + sizeof(record_t) * m_EntriesCount);
log("records_add at: %p", rec);
memcpy(entry->name, name, strlen(name));
rec->start = start;
rec->end = end;
m_EntriesCount++;
}
void records_print() {
log("records print:");
for(int i = 0; i < m_EntriesCount; i++) {
record_t* entry = (record_t*)m_Entries + sizeof(record_t) * m_EntriesCount;
log("%s %p %p", entry->name, entry->start, entry->end);
}
}
F. My output is this:
Code: Select all
record_size: 0x80, 128
records base addr: 0x0000000000090000
records_add at: 0x0000000000090000
records_add at: 0x0000000000090080
records print:
i: 0, name: start: (nil) end: (nil)
i: 1, name: start: (nil) end: (nil)
1. What exactly am I doing wrong, mixing up pointer dereferencing / not dereferencing correctly?
2. What is the correct way to use an address provided by the linker as the base for an array of structs?
3. Is there is correct method of doing this where I have a typed array (so record_t records[] instead of a void*)?
4. The memory offset is correct, because size = 0x80, and the second entry (1) is being placed at 0x90080? Am I mixing up bytes / hex / decimal?
5. What is the correct way to do this overall?
Thank you kindly.