In the K.N.King book, there’s an example:
viewmemory.c
/* Allows the user to view regions of computer memory */
#include <stdio.h>
#include <ctype.h>
typedef unsigned char BYTE;
int main(void)
{
unsigned int addr;
int i, n;
BYTE *ptr;
printf("Address of main function: %x\n", (unsigned int) main);
printf("Address of addr variable: %x\n", (unsigned int) &addr);
printf("\nEnter a (hex) address: ");
scanf("%x", &addr);
printf("Enter number of bytes to view: ");
scanf("%d", &n);
printf("\n");
printf(" Address Bytes Characters\n");
printf(" ------- ------------------------------- ----------\n");
ptr = (BYTE *) addr;
for (; n > 0; n -= 10) {
printf("%8X ", (unsigned int) ptr);
for (i = 0; i < 10 && i < n; i++)
printf("%.2X ", *(ptr + i));
for (; i < 10; i++)
printf(" ");
printf(" ");
for (i = 0; i < 10 && i < n; i++) {
BYTE ch = *(ptr + i);
if (!isprint(ch))
ch = '.';
printf("%c", ch);
}
printf("\n");
ptr += 10;
}
return 0;
}
For some reason, when I try to enter addr variable address as the parameter, it has a segmentation fault error. However, in the book’s example and the screenshot from this site in Hangul, there’s no such error?
When I try using gdb
to check the issue, here’s what I get:
gdb
$ gdb ./a.out --silent
Reading symbols from ./a.out...
(gdb) run
Starting program: /home/<username>/Desktop/c-programming-a-modern-approach/low-level-programming/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/gnu/store/zvlp3n8iwa1svxmwv4q22pv1pb1c9pjq-glibc-2.39/lib/libthread_db.so.1".
Address of main function: 401166
Address of addr variable: ffffd678
Enter a (hex) address: ffffd678
Enter number of bytes to view: 64
Address Bytes Characters
------- ------------------------------- ----------
Program received signal SIGSEGV, Segmentation fault.
0x000000000040123a in main () at viewmemory.c:31
warning: Source file is more recent than executable.
31 printf ("%.2X ", *(ptr + i));
(gdb)
What is going on? By the way, I am using Guix, if that matters in any way. Here’s the output for ldd
:
ldd
$ ldd ./a.out
linux-vdso.so.1 (0x00007ffecdda9000)
libgcc_s.so.1 => /gnu/store/w0i4fd8ivrpwz91a0wjwz5l0b2ralj16-gcc-11.4.0-lib/lib/libgcc_s.so.1 (0x00007fcd2627a000)
libc.so.6 => /gnu/store/zvlp3n8iwa1svxmwv4q22pv1pb1c9pjq-glibc-2.39/lib/libc.so.6 (0x00007fcd2609c000)
Depending on the value of ptr and i, you might be accessing data out of your process’ memory space.
But I am trying to read memory assigned by
addr
variable, which seems to work just fine on the textbook example? (see pic in the link) However, when I try to do the same, I get this:$ ./a.out Address of main function: 401166 Address of addr variable: 3f4c4310 Enter a (hex) address: 3f4c4310 Enter number of bytes to view: 40 Address Bytes Characters ------- ------------------------------- ---------- Segmentation fault
The book is from 1996, and there’s a decent chance that the screenshot was made on an older OS that does not have the same memory protection features as a modern OS would have.
Try a few of the following and see if they segfault:
- Read only as much memory as the size of the pointer addr
- Offset the value of addr by -64 and read 64 from there
- Do the same but with smaller values
The pointer
addr
is actually undefined, and currently points to some random every time it is executed. Could this be where the memory protection is being triggered, preventing access to other segments?Could be, yeah.
I guess I didn’t read the code well enough, but I was expecting
addr
to point to somewhere on the stack.I guess that’s something to try - declare and assign a variable and then print the address of it, and then use that to take a look at stack memory.