weird issue slab freelist points to non canonical address

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
RayanMargham
Member
Member
Posts: 40
Joined: Tue Jul 05, 2022 12:37 pm

weird issue slab freelist points to non canonical address

Post by RayanMargham »

Okay so, I'm working on a slab allocator and heres the thing. after enough allocations the slab allocator freelist starts pointing to non-canonical addresses? (2006000067E01B). I do not understand what im doing wrong? my slab allocator SHOULD work and this like makes no sense

this is my slab allocator code

Code: Select all

struct pmm_node
{
    struct pmm_node *next;
};
struct Header
{
    size_t size;
    struct Header *next;
    struct pmm_node *freelist;
};
struct cache
{
    struct Header *slabs;
    size_t size;
};

struct cache kmalloc_cache[8];

void init_cache(struct cache *cache, size_t size)
{
    char ****[64] = "";
    cache->size = size;
    void *page = pmm_alloc_singlep();
    struct Header *h = page + hhdm_request.response->offset;
    h->size = size;
    cache->slabs = (uint64_t)h;
    
    size_t obj_amount = (4096 - sizeof(struct Header)) / (size);
    write_color(ctx, "Slab: Creating Cache of Object Count: ", 0);
    write(ctx, itoa(****, obj_amount));
    write(ctx, " and Size: ");
    write(ctx, itoa(****, size));
    write(ctx, "\n");
    struct pmm_node *start = (uint64_t)h + sizeof(struct Header);
    h->freelist = start;
    struct pmm_node *prev = start;
    for (int i = 1; i < obj_amount; i++)
    {
        struct pmm_node *new = (uint64_t)start + (i * size);
        prev->next = new;
        prev = new;
    }
    write_color(ctx, "Slab: Cache Created!\n", 0);
}

struct Header *make_slab(size_t size)
{
    char ****[64] = "";
    void *page = pmm_alloc_singlep();
    struct Header *h = page + hhdm_request.response->offset;
    h->size = size;
    size_t obj_amount = (4096 - sizeof(struct Header)) / (size);
    struct pmm_node *start = (uint64_t)h + sizeof(struct Header);
    h->freelist = start;
    struct pmm_node *prev = start;
    for (int i = 1; i < obj_amount; i++)
    {
        struct pmm_node *new = (uint64_t)start + (i * size);
        prev->next = new;
        prev = new;
    }
    return h;
}
size_t next_pow2(size_t v)
{
    v--;
    v |= v >> 1;
    v |= v >> 2;
    v |= v >> 4;
    v |= v >> 8;
    v |= v >> 16;
    v++;
    return v;
}
static inline struct cache *search_for_bigenoughcache(size_t size)
{
    for (int i = 0; i < 8; i++)
    {
        if (kmalloc_cache[i].size >= size)
        {
            return &kmalloc_cache[i];
        }
    }
    return NULL;
}
void *slab_alloc(struct cache *cache)
{
    char ****[64] = "";
    struct Header *h = cache->slabs;
    while (h != NULL)
    {
        if (h->freelist != NULL)
        {
            struct pmm_node *him = h->freelist;
            serial_print("memory address: ");
            serial_print(itoah(****, (uint64_t)him));
            serial_print(" size: ");
            serial_print(itoa(****, h->size));
            serial_print("\n");
            h->freelist = him->next;
            
            return him;
        }
        else
        {
            if (h->next == NULL)
            {
                break;
            }
            h = h->next; // go to next header
        }
    }
    serial_print("um\n");
    // no slabs at all on this cache
    // allocate new slab
    struct Header *new_slab = make_slab(cache->size);
    h->next = new_slab;
    struct pmm_node *we = new_slab->freelist;
    new_slab->freelist = new_slab->freelist->next;
    serial_print(itoah(****, (uint64_t)new_slab->freelist));
    serial_print("making new slab\n");
    return we;
}
void free(void *addr)
{
    serial_print("before\n");
    char da[64] = "";
    if ((uint64_t)addr == 0)
    {
        return;
    }
    struct Header *h = (uint64_t)addr & ~0xFFF;
    struct cache *rightcache = NULL;
    for (int i = 0; i < 8; i++)
    {
        if (kmalloc_cache[i].size == h->size)
        {
            rightcache = &kmalloc_cache[i];
        }
    }
    if (rightcache == NULL)
    {
        return;
    }
    struct pmm_node *new = (uint64_t)addr;
    new->next = h->freelist;
    h->freelist = new;
    // put header into header freelist if not
    struct Header *prev = NULL;
    struct Header ***** = rightcache->slabs;
    while (**** != NULL)
    {
        if (**** == h)
        {
            return; // no need to do anything
        }
        else
        {
            prev = ****;
            **** = ****->next;
        }
    }
    // slab was fully used and now needs to be put back onto the header list
    serial_print("go back\n");
    prev->next = h;
    return;
}

void *kmalloc(size_t size)
{
    char ****[64] = "";
    struct cache *ca = search_for_bigenoughcache(next_pow2(size));
    if (ca == NULL)
    {
        serial_print("COUDNLT FIND FOR THIS SIZE BOZO!\n");
        return;
    }
    return slab_alloc(ca);
}
void init_slabs()
{
    init_cache(&kmalloc_cache[0], 8);
    init_cache(&kmalloc_cache[1], 16);
    init_cache(&kmalloc_cache[2], 32);
    init_cache(&kmalloc_cache[3], 64);
    init_cache(&kmalloc_cache[4], 128);
    init_cache(&kmalloc_cache[5], 256);
    init_cache(&kmalloc_cache[6], 512);
    init_cache(&kmalloc_cache[7], 1024);
}
i do NOT understand whats going on its causing me a lot of frustration
User avatar
iansjack
Member
Member
Posts: 4683
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: weird issue slab freelist points to non canonical addres

Post by iansjack »

Have you tried running the code under a debugger? That should make the error fairly easy to find.
RayanMargham
Member
Member
Posts: 40
Joined: Tue Jul 05, 2022 12:37 pm

Re: weird issue slab freelist points to non canonical addres

Post by RayanMargham »

I have, I could not find the issue.
User avatar
iansjack
Member
Member
Posts: 4683
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: weird issue slab freelist points to non canonical addres

Post by iansjack »

Look at the values returned by each allocation. Do they all look reasonable apart from the failing one. If so, set a breakpoint after the last correct allocation and single-step through the failing allocation.

My guess would be that it’s not just the last allocation that is unreasonable; it just the one that causes an error rather than returning an erroneous result.

You can run the allocator as a user process under your host OS (Linux or Windows - or Mac OS) to make the debugging easier.
RayanMargham
Member
Member
Posts: 40
Joined: Tue Jul 05, 2022 12:37 pm

Re: weird issue slab freelist points to non canonical addres

Post by RayanMargham »

I tried, i printed everything as well. the only thing weird is that one of the frees uacpi (the acpi library that is stress testing my allocator) calls points to a header that makes absolutely no sense but i have a check in my free function if the header makes like zero sense and it shouldnt really affect anything?
User avatar
iansjack
Member
Member
Posts: 4683
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: weird issue slab freelist points to non canonical addres

Post by iansjack »

I find it difficult to follow your code as it is full of oddities like

Code: Select all

char ****[64] = "";
undeclared variables and functions

Code: Select all

write(ctx, itoa(****, obj_amount));
and, most confusingly, few comments describing the purpose and expected inputs and outputs of the various functions (what is the function

Code: Select all

size_t next_pow2(size_t v)
supposed to do?). Have you tested the functions individually to check that they provide the expected output for a given input?

As it is, the code won't compile so there's not much more I can add.
RayanMargham
Member
Member
Posts: 40
Joined: Tue Jul 05, 2022 12:37 pm

Re: weird issue slab freelist points to non canonical addres

Post by RayanMargham »

sorry this is just a snippit of my code.

I'll commit the code and upload to github

heres the repo: https://github.com/rayanmargham/NyaOS/tree/master
RayanMargham
Member
Member
Posts: 40
Joined: Tue Jul 05, 2022 12:37 pm

Re: weird issue slab freelist points to non canonical addres

Post by RayanMargham »

Solved issue of slab by memzeroing memory

New Issue with my vmm tho... Causing memory corruption in the slab allocator

love my life!
thewrongchristian
Member
Member
Posts: 422
Joined: Tue Apr 03, 2018 2:44 am

Re: weird issue slab freelist points to non canonical addres

Post by thewrongchristian »

RayanMargham wrote:Solved issue of slab by memzeroing memory

New Issue with my vmm tho... Causing memory corruption in the slab allocator

love my life!
In debug builds (gated by the DEBUG macro), add code to initialise allocated memory to known sentinel values, that are unlikely to be interpreted as a valid pointer if dereferenced.

That way, any allocated memory that you happen to dereference that you have not initialised will likely result in a fault, and such memory is also easily identifiable as uninitialised just by inspection of the data.

I fill my free'd memory with 0xf8, and my newly allocated memory with 0x0a (not ideal, because that may dereference to a user address, better change that!)

The other thing that might be worth doing in debug mode is tagging allocations with source file and line information. That way, should you get repeatable corruption, you have a chance of finding the source of the corrupted allocation, which may give you clues as to where the corruption is happening.
Post Reply