Login
Username:

Password:

Remember me



Lost Password?

Register now!

Sections

Who's Online
70 user(s) are online (64 user(s) are browsing Forums)

Members: 0
Guests: 70

more...

Support us!

Headlines

 
  Register To Post  

« 1 (2)
Re: Catching memory corruption "in the act"
Amigans Defender
Amigans Defender


See User information
@msteed

Quote:
I normally use the CLIENT "ProgramName" option with MemGuard, so only the program I'm testing is monitored;

I've tried that of course; crashes anyway

The Rear Window blog

AmigaOne X5000 @ 2GHz / 4GB RAM / Radeon RX 560 / ESI Juli@ / AmigaOS 4.1 Final Edition
SAM440ep-flex @ 667MHz / 1GB RAM / Radeon 9250 / AmigaOS 4.1 Final Edition
Go to top
Re: Catching memory corruption "in the act"
Home away from home
Home away from home


See User information
@trixie

Are you speaking of a client / server option, so it sends TCP packets Well as long as OS does not completely freezes because of corruption.

(NutsAboutAmiga)

Basilisk II for AmigaOS4
AmigaInputAnywhere
Excalibur
and other tools and apps.
Go to top
Re: Catching memory corruption "in the act"
Quite a regular
Quite a regular


See User information
Back to the original topic, I was finally able to try the MMU protection method. Here's my example program:
#include <proto/exec.h>

#include <stdio.h>
#include <stdlib.h>

#define BUFFER_SIZE 48
#define MEM_ALIGN_SIZE 4096
#define MEM_GUARD_SIZE 4096

void *AllocMemory(int sizeint protect)
{
    
UBYTE *ptr IExec->AllocVecTags(MEM_GUARD_SIZE size,
        
AVT_Type,              MEMF_PRIVATE,
        
AVT_Alignment,         MEM_ALIGN_SIZE,
        
TAG_END);
    if (!
ptr) return NULL;

    if (
protect)
    {
        
struct MMUIFace *IMMU = (struct MMUIFace *)IExec->GetInterface((struct Library *)SysBase, (CONST_STRPTR)"MMU"1NULL);
        
ULONG attrs IMMU->GetMemoryAttrs(ptr0);
        
IMMU->SetMemoryAttrs(ptrMEM_GUARD_SIZE, (attrs MEMATTRF_READ_ONLY));
        
IExec->DropInterface((struct Interface *)IMMU);
    }

    return 
ptr ? (ptr MEM_GUARD_SIZE) : NULL;
}

void FreeMemory(void *block)
{
    if (!
block) return;
    
UBYTE *ptr = (UBYTE *)block;
    
IExec->FreeVec(ptr MEM_GUARD_SIZE);
}

int main(int argcchar *argv[])
{
    
BOOL protect = (argc 1) ? atoi(argv[1]) : 0;
    
printf("allocating %d bytes protect %d\n"BUFFER_SIZEprotect);
    
UBYTE *buf AllocMemory(BUFFER_SIZEprotect);
    if (!
buf)
    {
        
printf("allocation failed\n");
        return 
1;
    }

    
printf("valid writes...\n");
    for (
int i 0BUFFER_SIZEi++)
    {
        
buf[i] = 0xFF;
    }
    
printf("invalid write...\n");
    
buf[-1] = 0xFF;
    
printf("invalid writes...\n");
    for (
int i 0MEM_GUARD_SIZEi++)
    {
        
buf[-i] = 0xFF;
    }

    
printf("freeing memory\n");
    
FreeMemory(buf);

    return 
0;
}

This works in my simple test case, but there's one catch: the actual project does a metric ton of small memory allocations. The 4KB overhead plus the alignment requirement makes the memory fragmented to the point where the allocations start to fail, even with a 512MB Z3 RAM expansion. I tried smaller guard blocks while keeping the alignment as 4KB, but that ended up causing all sorts of freezes and crashes.
I guess my only option is Linux? :(

This is just like television, only you can see much further.
Go to top
Re: Catching memory corruption "in the act"
Just popping in
Just popping in


See User information
Quote:

I guess my only option is Linux? :(


If a PPC binary of the program exists: you can run 32bit or 64bit PPC big endian programs on little endian 64 bit x64 Linux with qemu user mode emulatation ("qemu-ppc" instead of "qemu-system-ppc"). You don't need to have PPC Linux installed, only download some Linux PPC iso and loop-mount it (and likely some filesytem image inside that as well) so you can tell qemu with "-L" where to pick up some PPC versions of libs the PPC binary needs.

I recently tried this with old (2011) version of 32 bit AROS PPC hosted on Linux version and it works pretty well. On old PC here (10 years old?) it "boots" into WB in 3 to 4 seconds (x86 AROS hosted debug version "boots" in maybe 0.5 seconds).

Go to top
Re: Catching memory corruption "in the act"
Quite a regular
Quite a regular


See User information
That sounds promising, because I had a terrible luck trying to install recent PPC Linux distros in QEMU. The project can be built for i386 Linux I think I could make a PPC executable with reasonable effort.
I saw that GDB is supported via user mode emulation, but I guess I'm going to need Valgrind too to catch the illegal writes outside the allocated blocks?

This is just like television, only you can see much further.
Go to top
Re: Catching memory corruption "in the act"
Quite a regular
Quite a regular


See User information
@BSzili
I don't know if valgrind works with user mode emulation (I've only found old tickets that said it did not work but could be fixed since). Otherwise there are docs at https://www.qemu.org/docs/master/system/ppc/amigang.html about running Linux on my boards in QEMU. Or for Linux any other PPC board may be used which can probably run more recent distros but PPC emulation is quite neglected. But you can use up to 2GB memory with AmigaOS on QEMU.
Another idea, if you can replace the allocation in the code you're debugging (e.g. with some preprocessor #defines) to call your own wrapper you could allocate more memory for some guard bytes before and after the address returned to the application then you can check it on free or when a crash occurs.

Go to top
Re: Catching memory corruption "in the act"
Home away from home
Home away from home


See User information
@BSzili

What are you trying to do?

If I read your code correct, you allocated memory, you protect it, and then return memory after the MEM_GUARD_SIZE? what is that supposed to do?

Typically, if you have broken for loop or while loop… it’s the end of the memory you need to protect, not the beginning of memory. even if did protect end of memory. you have problem with the memory page size, [protected][data][alignment][protected]… you might not catch bug sense you likely to write into alignment part.

pointer are not well understood by many developers, a pointer is a element.
“Ptr+=10;” is the offset: “sizeof(*ptr) * 10”; 10 is not in bytes its number of elements of the pointer to increment, this why always need to cast to byte pointers, before doing any additions, unless you intend something else.


wont it be better to create a memory copy protect, concept instead..

APTR DoublicateAsReadOnly(APTR src, size_s size);
void FreeReadOnly(APTR addr);

1. Allocate memory,
2. copy memory,
3. protect memory.

Crashes are often caused by non-initialized offsets, or pointers. Random crap in memory, causing pointers to be set, or offsets being set to something else than 0. It should be one of the prime suspects. Besides making sure you actually got memory after an allocation. Also, se lot developers who do not set pointer to NULL after freeing. yeh sure it faster if you don’t but it’s not uncommon to create a cleanup routine and accidentally call it twice because you forgot a return or a break.
stack corruption can be a issue, lets say you array with 10 items, it’s easy to accidently writ 11 items into it and corrupt next variable in the stack, its easy add extra variable after the array with 0xCAFECAFE or something like that, if want to check that array do not overwrite next variable on the stack..

Crashes on addresses like 0xFFFFF424, is good indication of zero pointer somewhere in the code.


Edited by LiveForIt on 2025/7/4 13:26:26
Edited by LiveForIt on 2025/7/4 14:25:18
Edited by LiveForIt on 2025/7/4 14:28:21
(NutsAboutAmiga)

Basilisk II for AmigaOS4
AmigaInputAnywhere
Excalibur
and other tools and apps.
Go to top

  Register To Post
« 1 (2)

 




Currently Active Users Viewing This Thread: 1 ( 0 members and 1 Anonymous Users )




Powered by XOOPS 2.0 © 2001-2024 The XOOPS Project