Scruffers
Scruffers

Reputation: 5074

Viewing Memory in GDB Outside of Process Space (mmap)

QUESTION:

For educational purposes, I'm in the process of trying to understand exactly how the RaspberryPI interfaces with its GPIO headers. I have a simple program that control an LED on an expansion board that works well. However, I wanted to use GDB to see the program changing bits in the mapped control registers. Normally I would do something like this in GDB:

x /t 0x20200000

But this seems to result in the following error, presumably as the target memory is not in the process space:

0x20200000: Cannot access memory at address 0x20200000

I tried mapping a memory region but didn't seem to help.

mem 0x20200000 0x20208192

I also true to write a function to call from GDB, but couldn't figure out how to write something that returned entire block of memory I am interested in so can view as binary (I don't want to peek each byte as write bits are quite spread out over area). Is there any way I can do this in GDB?

Supporting Code

Memory addresses to map:

#define BCM2708_PERI_BASE   0x20000000
#define GPIO_BASE           (BCM2708_PERI_BASE + 0x200000)

Pointer to mapped memory:

static volatile uint32_t *gpio ;

Mapping routine:

int gpio_init (void)
{
  int      fd ;
  uint8_t *gpioMem;

  if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
  {
    fprintf (stderr, "gpio_init: unable to open /dev/mem: %s\n", strerror (errno)) ;
    return -1 ;
  }

  if ((gpioMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
  {
    fprintf (stderr, "gpio_init: malloc failed: %s\n", strerror (errno)) ;
    return -1 ;
  }

  if (((uint32_t)gpioMem % PAGE_SIZE) != 0)
    gpioMem += PAGE_SIZE - ((uint32_t)gpioMem % PAGE_SIZE) ;

  gpio = (uint32_t *)mmap((caddr_t)gpioMem, BLOCK_SIZE, PROT_READ|PROT_WRITE,  MAP_SHARED|MAP_FIXED, fd, GPIO_BASE) ;

  if ((int32_t)gpio < 0)
  {
    fprintf (stderr, "gpio_init: mmap failed: %s\n", strerror (errno)) ;
    return -1 ;
  }

  return 0 ;
}

Upvotes: 1

Views: 1649

Answers (1)

caf
caf

Reputation: 239171

The physical memory address 0x20200000 is being mapped into your process address space at an address stored in the variable gpio, so that's the address you should be examining in gdb. Just print the contents of gpio after gpio_init() has been called and use that value.

As an aside the way the mapping is done is confused. There is no need to allocate a memory block with malloc and then map over it, and it also fails to close the file descriptor. That entire function could be better written as:

int gpio_init (void)
{
  int      fd ;

  if ((fd = open ("/dev/mem", O_RDWR) ) < 0)
  {
    fprintf (stderr, "gpio_init: unable to open /dev/mem: %s\n", strerror (errno)) ;
    return -1 ;
  }

  gpio = mmap(NULL, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ;

  if (gpio == MAP_FAILED)
  {
    fprintf (stderr, "gpio_init: mmap failed: %s\n", strerror (errno)) ;
    close(fd);
    return -1 ;
  }

  close(fd);
  return 0 ;
}

Upvotes: 2

Related Questions