RAM test steps through, but fails when running - c

The project I'm working on has to test the data memory of a dsPIC30F chip before the program runs. Due to industry requirements, we cannot utilize any pre-defined libraries that C has to offer. That being said, here is my methodology for testing the RAM:
Step 1 - Write the word 0xAAAA to a specific location in memory (defined by a LoopIndex added to the START_OF_RAM address)
Step 2 - increment LoopIndex
Step 3 - Repeat Steps 1-2 until LoopIndex + START_OF_RAM >= END_OF_RAM
Step 4 - Reset LoopIndex = 0
Step 5 - Read memory at LoopIndex+START_OF_RAM
Step 6 - If memory = 0xAAAA, continue, else throw RAM_FAULT_HANDLER
Step 7 - increment LoopIndex
Step 8 - Repeat Step 5 - 7 until LoopIndex + START_OF_RAM >= END_OF_RAM
Now, the weird part is that I can step through the code, no problem. It will slowly loop through each memory address for as long as my little finger can press F8, but as soon as I try to set up a breakpoint at Step 4, it throws a random, generic interrupt handler for no apparent reason. I've thought that it could be due to the fact that the for() I use may exceed END_OF_RAM, but I've changed the bounds of the conditions and it still doesn't like to run.
Any insight would be helpful.
void PerformRAMTest()
{
// Locals
uint32_t LoopIndex = 0;
uint16_t *AddressUnderTest;
uint32_t RAMvar = 0;
uint16_t i = 0;
// Loop through RAM and write the first pattern (0xAA) - from the beginning to the first RESERVED block
for(LoopIndex = 0x0000; LoopIndex < C_RAM_END_ADDRESS; LoopIndex+= 2)
{
AddressUnderTest = (uint32_t*)(C_RAM_START_ADDRESS + LoopIndex);
*AddressUnderTest = 0xAAAA;
}// end for
for(LoopIndex = 0x0000; LoopIndex < C_RAM_END_ADDRESS; LoopIndex += 2)
{
AddressUnderTest = (uint32_t*)(C_RAM_START_ADDRESS + LoopIndex);
if(*AddressUnderTest != 0xAAAA)
{
// If what was read does not equal what was written, log the
// RAM fault in NVM and call the RAMFaultHandler()
RAMFaultHandler();
}// end if
}
// Loop through RAM and write then verify the second pattern (0x55)
// - from the beginning to the first RESERVED block
// for(LoopIndex = C_RAM_START_ADDRESS; LoopIndex < C_RAM_END_ADDRESS; LoopIndex++)
// {
// AddressUnderTest = (uint32_t*)(C_RAM_START_ADDRESS + LoopIndex);
// *AddressUnderTest = 0x5555;
// if(*AddressUnderTest != 0x5555)
// {
// // If what was read does not equal what was written, log the
// // RAM fault in NVM and call the RAMFaultHandler()
// RAMFaultHandler();
// }
// }
}// end PerformRAMTest
You can see that the second pass of the test writes 0x55. This was the original implementation that was given to me, but it never worked (at least as far as debugging/running; the same random interrupt was encountered with this method of writing then immediately reading the same address before moving on)
UPDATE: After a few Clean&Builds, the code will now run through until it hits the stack pointer (WREG15), skip over, then errors out. Here is a new sample of the code in question:
if(AddressUnderTest >= &SPLIMIT && AddressUnderTest <= SPLIMIT)
{
// if true, set the Loop Index to point to the end of the stack
LoopIndex = (uint16_t)SPLIMIT;
}
else if(AddressUnderTest == &SPLIMIT) // checkint to see if AddressUnderTest points directly to the stack [This works while the previous >= &SPLIMIT does not. It will increment into the stack, update, THEN say "oops, I just hit the stack" and error out.]
{
LoopIndex = &SPLIMIT;
}
else
{
*AddressUnderTest = 0xAAAA;
}

I think you actually want (C_RAM_START_ADDRESS + LoopIndex) < C_RAM_END_ADDRESS as your loop condition. Currently, you are looping from C_RAM_START_ADDRESS to C_RAM_START_ADDRESS + C_RAM_END_ADDRESS which I assume is writing past the end of the RAM.
You also should really factor out the repeated code into a separate function that takes the test pattern as a parameter (DRY).

Okay, so there are a number of things that we can look at to get a better understanding of where your problem may be. There are some things that I would like to point out - and hopefully we can figure this out together. The first thing that I noticed that seems a little out of place is this comment:
"...total RAM goes to 0x17FFE..."
I looked up the data sheet for the dsPIC30F6012A . You can see in Figure 3-8 (pg. 33), that the SRAM space is 8K and runs from 0x0800 to 0x2800. Also, there is this little tidbit:
"All effective addresses are 16 bits wide and point to bytes within the data space"
So, you can use 16 bit values for your addresses. I am a little confused by your update as well. SPLIM is a register that you set the value for - and that value limits the size of your stack. I'm not sure what the value for your SPLIMIT is, but W15 is your actual stack pointer register, and the value that is stored there is the address to the top of your stack:
"There is a Stack Pointer Limit register (SPLIM) associated
with the Stack Pointer. SPLIM is uninitialized at
Reset. As is the case for the Stack Pointer, SPLIM<0>
is forced to ‘0’ because all stack operations must be
word aligned. Whenever an Effective Address (EA) is
generated using W15 as a source or destination
pointer, the address thus generated is compared with
the value in SPLIM. If the contents of the Stack Pointer
(W15) and the SPLIM register are equal and a push
operation is performed, a Stack Error Trap will not
occur."
Finally, the stack grows from the lowest available SRAM address value up to SPLIM. So I would propose setting the SPLIM value to something reasonable, let's say 512 bytes (although it would be best to test how much room you need for your stack).
Since this particular stack grows upwards, I would start at 0x0800 plus what we added for the stack limit and then test from there (which would be 0x1000). This way you won't have to worry about your stack region.
Given the above, here is how I would go about doing this.
void PerformRAMTest (void)
{
#define SRAM_START_ADDRESS 0x0800
/* Stack size = 512 bytes. Assign STACK_LIMIT
to SPLIM register during configuration. */
#define STACK_SIZE 0x0200
/* -2, see pg 35 of dsPIC30F6012A datasheet. */
#define STACK_LIMIT ((SRAM_START_ADDRESS + STACK_SIZE) - 2)
#define SRAM_BEGIN_TEST_ADDRESS ((volatile uint16_t *)(STACK_LIMIT + 2))
#define SRAM_END_TEST_ADDRESS 0x2800
#define TEST_VALUE 0xAAAA
/* No need for 32 bit address values on this platform */
volatile uint16_t * AddressUnderTest = SRAM_BEGIN_TEST_ADDRESS
/* Write to memory */
while (AddressUnderTest < SRAM_END_TEST_ADDRESS)
{
*AddressUnderTest = TEST_VALUE;
AddressUnderTest++;
}
AddressUnderTest = SRAM_BEGIN_TEST_ADDRESS;
/* Read from memory */
while (AddressUnderTest < SRAM_END_TEST_ADDRESS)
{
if (*AddressUnderTest != TEST_VALUE)
{
RAMFaultHandler();
break;
}
else
{
AddressUnderTest++;
}
}
}
My code was a bit rushed so I am sure there are probably some errors (feel free to edit), but hopefully this will help get you on the right track!

Related

Efficiently find a sequence within a buffer

So I have a buffer that I am filling with a frame that has a maximum of 1200 bytes and is variably sized. I know the frame is complete when I get a tail sequence that is always the same and doesn't occur otherwise. So I am trying to find how to most efficiently detect that tail sequence. This is embedded so ideally the fewer function calls and data structures I use the better.
Here is what I have thus far:
//I am reading off of a circular buffer so this is checking that I still have unread bytes
while (cbuf_last_written_index != cbuf_last_read_index) {
buffer[frame_size] = circular_buffer[cbuf_last_read_index];
//this function does exactly what it says and just maintains circular buffer correctness
increment_cbuf_read_index_count();
frame_size++;
//TODO need to make this more efficient
int i;
uint8_t sync_test_array[TAIL_SYNC_LENGTH] = {0};
//this just makes sure I have enough in the frame to even bother checking the tail seq
if (frame_size > TAIL_SYNC_LENGTH) {
for (i = 0; i < TAIL_SYNC_LENGTH; i++) {
//sets the test array equal to the last TAIL_SYNC_LENGTH elements the buffer
sync_test_array[i] = buffer[(frame_size - TAIL_SYNC_LENGTH) + i];
}
if (sync_test_array == tail_sequence_array) {
//I will toggle a pin here to notify that the frame is complete
//get out of the while loop because the following bytes are part of the next frame
break;
}
}
//end efficiency needed area
}
So basically for each new byte that is added to the frame I am checking the last x bytes (will probably actually be ~8) to see if they are the tail sequence. Can you think of a better way to do this?
Implement it as a state machine.
If your tail sequence is 1,2,5, the psuedo code would be:
switch(current_state) {
IDLE: next_state = ONE_SEEN if new_byte == 1 else next-state = IDLE
ONE_SEEN: next_state = TWO_SEEN if new_byte == 2 else next_state = IDLE
TWO_SEEN: next_state = TERMINATE if new_byte == 5 else next_state = IDLE
}

Find how many free and used page there are in a address range

I'm trying to port liballoc on a small kernel that I'm writing for my thesis.
In order to do that, I need a function that scan a range of address to find free (and used) pages.
I wrote that function that scan from and address (it should be pagetable aligned) and print if a page is free or is used:
uint32_t check_pages(uint32_t startAddr,uint32_t length){
pdirectory* dir = vmm_get_directory ();
pd_entry* pagedir = dir->m_entries;
int cfreepage = 0;
int cusedpage = 0;
uint32_t x = 0, y = 0;
for(x = startAddr; x < (startAddr+length) ; x+=4096*1024){ // check 1 pagetable at a time
if(pagedir[x>>22] != 0){ // check if pagetable exist
ptable* table =(ptable*) pagedir[x>>22];
for(y=x;;y+=4096){ // scan every single pages in the pagetable
pt_entry* page = (pt_entry*)table->m_entries [ PAGE_TABLE_INDEX (y) ];
if(((uint32_t)(page)>>22) != 0){ // check if a page is present FIXME this might be the problem
cusedpage++;
kernelPrintf("Found used page number: %d\n",PAGE_TABLE_INDEX (y));
}
else{
cfreepage++;
kernelPrintf("Found free page number: %d\n",PAGE_TABLE_INDEX (y));
}
if(PAGE_TABLE_INDEX (y)==1023) break;
}
}
else{ // if a pagetable doesn't exist add 1024 free pages to the counter
kernelPrintf("found free pagetable! (1024 free pages)\n");
cfreepage+=1024;
}
}
kernelPrintf("Used Pages Found: %d\n",cusedpage);
kernelPrintf("Free Pages Found: %d\n",cfreepage);
return 0;
}
This code works, but have one issue: some pages that are used, will result free..
I think that the problem is this if:
if(((uint32_t)(page)>>22) != 0)
There might be a better way to check if a page is used or not..
Thanks for the help
if (x >> 22) checks if any bit higher than 21th is set. I have no clue why you shift by 22 (looks like an arbitrary number - why the heck do you do it this way?). If you want to check if an entry is present (in a paging structure of any level), check bit 0 of that entry. Note that checking the highest bits would only work if the entry was assigned with high address (wouldn't catch, say, 0x100000).
Also note that if present bit is 0, all the other bytes are ignored, hence the OS can store any values in them, which might also be an information that will come handy one day.
This maybe not what you want but it might help.
I had once a similar task to do (memory allocator for an embedded system), here is what I did:
Define and align the allocable pages
Define elsewhere an array that references all the pages: I update the arry[idx] value when I allocate/release a page and it makes the count easy

Understanding Logic Using Iteration for Master/Slave

I took over a project from unknown predecessor who had gone without proper documents and comments.
Now I am trying to analyze his codes, but it is hard to follow up.
Basically, there are 32 channels hook up with a micro controller. What he seems like trying to do is find slave channels between 32 channels once those information is sent from a server.
call nextslave()
for (scan=0 ; (scan = nextslave(chan, scan)) != -1 ; scan++)
nextslave() looks like below
/**
* nextslave - gets the channel number of the next slave channel
* associated with the master. returns -1 if no more slaves.
* channel and start are zero-based.
*/
short nextslave(short channel, short start)
{
short mask, major, minor;
unsigned char *p;
/* fix-up the slaveflag[] index values */
major = start / 8;
minor = start % 8;
/* init a pointer into the slaveflag[] array */
p = &(chparam[channel].slaveflag[major]);
/* now let us find the next slave channel (if any) */
for (; major < (NUMCHANS / 8) ; major++, p++)
{
minor &= 0x07;
for (mask = (0x01 << minor) ; minor < 8 ; mask <<= 1, minor++)
{
if (*p & mask)
{
/* found one so calculate channel# and return */
return ((major * 8) + minor);
}
}
}
/* if we reach here then there are no (more) slaves */
return (-1);
}
What I have analyzed so far is:
start variable keeps iterating until 32 in nextslave().
when the start var is 0~7, major var is 0 and minor var changes from 0 to 7,also mask var changes 1,2,4,8,16...
When the start var is 8 ~15, major var is 1, and minor var still keep changing from 0 to 7
Keep iterating until major var becomes 4.(I don't know the meaning of major var in his codes)
In second for loop, return something if *p(pointer to values from server) & mask is true
I am not clear about general idea about what he intended to for this process. Especially, in the second for loop, if there is no match up in if(*p&mask), then go back to the first for loop. However, minor variable was being increased without clearing out like 0. So once the code hits minor &= 0x07, the processor will do bitwise with the last value of minor although major var keeps increasing.
For instance, the range of minor var is 0 to 7 and there is no match up value, so ends up becoming 7 in the second for loop. Get out of the loop and go back to the first loop and increases major var by 1. But minor var is still 7, so the second loop will start like mask =(0x01<<minor) with minor =7.
I feel like need to reset minor =0 whenever getting out the second for loop, but I don't know what he was aiming for. He just wrote down "master/slave technique".
My Questions are:
Is it correct with my analysis?
How the master/slave technique is used for 32 channels getting ADC?
Is the reset code for minor var required? whenever getting out the second for loop.
If you have any idea, please answer anything that helps me out to understand his codes.
Thanks,
Jin

How can I deal with given situtaion related to Hardware change

I am maintaining a Production code related to FPGA device .Earlier resisters on FPGA are of 32 bits and read/write to these registers are working fine.But Hardware is changed and so did the FPGA device and with latest version of FPGA device we have trouble in read and write to FPGA register .After some R&D we came to know FPGA registers are no longer 32 bit ,it is now 31 bit registers and same has been claimed by FPGA device vendor.
So there is need to change small code as well.Earlier we were checking that address of registers are 4 byte aligned or not(because registers are of 32 bits)now with current scenario we have to check address are 31 bit aligned.So for the same we are going to check
if the most significant bit of the address is set (which means it is not a valid 31 bit).
I guess we are ok here.
Now second scenario is bit tricky for me.
if read/write for multiple registers that is going to go over the 0x7fff-fffc (which is the maximum address in 31 bit scheme) boundary, then have to handle request carefully.
Reading and Writing for multiple register takes length as an argument which is nothing but number of register to be read or write.
For example, if the read starts with 0x7fff-fff8, and length for the read is 5. Then actually, we can only read 2 registers (which is 0x7fff-fff8, and 0x7fff-fffc).
Now could somebody suggest me some kind of pseudo code to handle this scenario
Some think like below
while(lenght>1)
{
if(!(address<<(lenght*31) <= 0x7fff-fffc))
{
length--;
}
}
I know it is not good enough but something in same line which I can use.
EDIT
I have come up with a piece of code which may fulfill my requirement
int count;
Index_addr=addr;
while(Index_add <= 7ffffffc)
{
/*Wanted to move register address to next register address,each register is 31 bit wide and are at consecutive location. like 0x0,0x4 and 0x8 etc.*/
Index_add=addr<<1; // Guess I am doing wrong here ,would anyone correct it.
count++;
}
length=count;
The root problem seems to be that the program is not properly treating the FPGA registers.
Data encapsulation would help, and, instead of treating the 31-bit FPGA registers as memory locations, they should be abstracted.
The FPGA should be treated as a vector (a one-dimensional array) of registers.
The vector of N FPGA registers should be addressable by an register index in the range of 0x0000 through N-1.
The FPGA registers are memory mapped at base addr.
So the memory address = 4 * FPGA register index + base addr.
Access to the FPGA registers should be encapsulated by read and write procedures:
int read_fpga_reg(int reg_index, uint32_t *reg_valp)
{
if (reg_index < 0 || reg_index >= MAX_REG_INDEX)
return -1; /* error return */
*reg_valp = *(uint32_t *)(reg_index << 2 + fpga_base_addr);
return 0;
}
As long as MAX_REG_INDEX and fpga_base_addr are properly defined, then this code will never generate an invalid memory access.
I'm not absolutely sure I'm interpreting the given scenario correctly. But here's a shot at it:
// Assuming "address" starts 4-byte aligned and is just defined as an integer
unsigned uint32_t address; // (Assuming 32-bit unsigned longs)
while ( length > 0 ) // length is in bytes
{
// READ 4-byte value at "address"
// Mask the read value with 0x7FFFFFFF since there are 31 valid bits
// 32 bits (4 bytes) have been read
if ( (--length > 0) && (address < 0x7ffffffc) )
address += 4;
}

Buffer overflow in C

I'm attempting to write a simple buffer overflow using C on Mac OS X 10.6 64-bit. Here's the concept:
void function() {
char buffer[64];
buffer[offset] += 7; // i'm not sure how large offset needs to be, or if
// 7 is correct.
}
int main() {
int x = 0;
function();
x += 1;
printf("%d\n", x); // the idea is to modify the return address so that
// the x += 1 expression is not executed and 0 gets
// printed
return 0;
}
Here's part of main's assembler dump:
...
0x0000000100000ebe <main+30>: callq 0x100000e30 <function>
0x0000000100000ec3 <main+35>: movl $0x1,-0x8(%rbp)
0x0000000100000eca <main+42>: mov -0x8(%rbp),%esi
0x0000000100000ecd <main+45>: xor %al,%al
0x0000000100000ecf <main+47>: lea 0x56(%rip),%rdi # 0x100000f2c
0x0000000100000ed6 <main+54>: callq 0x100000ef4 <dyld_stub_printf>
...
I want to jump over the movl instruction, which would mean I'd need to increment the return address by 42 - 35 = 7 (correct?). Now I need to know where the return address is stored so I can calculate the correct offset.
I have tried searching for the correct value manually, but either 1 gets printed or I get abort trap – is there maybe some kind of buffer overflow protection going on?
Using an offset of 88 works on my machine. I used Nemo's approach of finding out the return address.
This 32-bit example illustrates how you can figure it out, see below for 64-bit:
#include <stdio.h>
void function() {
char buffer[64];
char *p;
asm("lea 4(%%ebp),%0" : "=r" (p)); // loads address of return address
printf("%d\n", p - buffer); // computes offset
buffer[p - buffer] += 9; // 9 from disassembling main
}
int main() {
volatile int x = 7;
function();
x++;
printf("x = %d\n", x); // prints 7, not 8
}
On my system the offset is 76. That's the 64 bytes of the buffer (remember, the stack grows down, so the start of the buffer is far from the return address) plus whatever other detritus is in between.
Obviously if you are attacking an existing program you can't expect it to compute the answer for you, but I think this illustrates the principle.
(Also, we are lucky that +9 does not carry out into another byte. Otherwise the single byte increment would not set the return address how we expected. This example may break if you get unlucky with the return address within main)
I overlooked the 64-bitness of the original question somehow. The equivalent for x86-64 is 8(%rbp) because pointers are 8 bytes long. In that case my test build happens to produce an offset of 104. In the code above substitute 8(%%rbp) using the double %% to get a single % in the output assembly. This is described in this ABI document. Search for 8(%rbp).
There is a complaint in the comments that 4(%ebp) is just as magic as 76 or any other arbitrary number. In fact the meaning of the register %ebp (also called the "frame pointer") and its relationship to the location of the return address on the stack is standardized. One illustration I quickly Googled is here. That article uses the terminology "base pointer". If you wanted to exploit buffer overflows on other architectures it would require similarly detailed knowledge of the calling conventions of that CPU.
Roddy is right that you need to operate on pointer-sized values.
I would start by reading values in your exploit function (and printing them) rather than writing them. As you crawl past the end of your array, you should start to see values from the stack. Before long you should find the return address and be able to line it up with your disassembler dump.
Disassemble function() and see what it looks like.
Offset needs to be negative positive, maybe 64+8, as it's a 64-bit address. Also, you should do the '+7' on a pointer-sized object, not on a char. Otherwise if the two addresses cross a 256-byte boundary you will have exploited your exploit....
You might try running your code in a debugger, stepping each assembly line at a time, and examining the stack's memory space as well as registers.
I always like to operate on nice data types, like this one:
struct stackframe {
char *sf_bp;
char *sf_return_address;
};
void function() {
/* the following code is dirty. */
char *dummy;
dummy = (char *)&dummy;
struct stackframe *stackframe = dummy + 24; /* try multiples of 4 here. */
/* here starts the beautiful code. */
stackframe->sf_return_address += 7;
}
Using this code, you can easily check with the debugger whether the value in stackframe->sf_return_address matches your expectations.

Resources