How to access a specific RAM location by address?

Asked

Viewed 4,823 times

9

I’m starting to study C/C++ pointers and it was something that caught my attention by the robustness and the range of possibilities. However, I can only access memory positions by assigning to my pointer an address of an already allocated variable, as in:

#include <stdio.h>

void main(){
    int x =0, *p =&x;
    printf("%x",p); 

    return 0;
} 

And the address of my pointer (as well as the address of my variables), in this case, is chosen by the Loader of the operating system, I think.

I would like to allocate my variables in specific memory positions (chosen by me), and I would also like to, for example, access the 0x000001 position of my RAM (Yes! I want to screw up the Operating System). Is this possible using pointers? Is there any other way to do this? What and how?

  • I think it is only possible to store in the heap isn’t it? Or I will have a memory violation. But I would really like to know how to do this.

  • I ended up accepting the @Guilhermeb’s reply for being more complete and explaining what happens "behind the scenes" that makes it impossible to allocate a pointer in a specific region of RAM. It also gave me some very useful details and explained how to use a kernel module so that I actually allocate the pointer wherever I want.

  • I appreciate the contribution of all, the two answers were very good, I will use the code of @Guilhermea in my embedded applications and this will help me a lot. Thank you all for your contribution.

2 answers

10


To begin, strictly speaking, you can only write and read data from valid pointers, i.e., pointers created from objects within your lives. A pointer to any other place is invalid and cannot be read or written, although it may exist (such as the NULL). But, of course, you’re talking about reality and practice, not how the perfect world should be.

In any modern operating system there is something called virtual memory (Virtual Memory). In this way each process exists and works only with its limited view of memory. A process sees memory as a large block of 16 exbibytes (I’m considering 64-bit) in which it has access to anywhere. At each address he tries to read, the system will translate the address that the process sees to the address that the data really is at. So two different processes can read exactly the same address and receive different data.

This virtual memory is divided into pages (usually blocks of 4 kibibytes) and the system has a table that assigns virtual pages to real pages. This is what allows the system, for example, to save a page not much used on the disk to free memory and recover it as soon as the process tries to read its address, all in a transparent way.

When you try to access an address that is not assigned in the virtual page table (or when you try to write to a read-only page, or run a non-executable one, etc.) you will have a memory breach. Your process will receive a SIGSEGV and will be finalized. A crash.

As much as you want to, it will not be possible to cause any damage to your system using just an ordinary process. You cannot read the kernel memory or read the memory of other processes simply using pointers like this. All you can do is read a page that doesn’t exist and the process will die.

Now... If you really want to cause problems, then you have to make your code run as a little more than a process. How about a kernel module? In this case you are the system itself and use real memory, you are in ring-0. In this situation you can read or write whatever you want. But note that trying to read an address out of memory, for example, will cause you a hardware exception. A beautiful blue screen or a Panic kernel for you.

You can also put your code on a microcontroller or something similar, running without the existence of an operating system.

  • Very interesting. So, if I use a kernel module I can have direct access to memory? Do I need to give permissions or do something like that? How I would do this?

  • 2

    @Avelino Yes. When it comes to Linux, you compile the code and install it as a kernel module (needs to be SU). Here’s a good guide: The Linux Kernel Module Programming Guide.

6

As already pointed out, you cannot say explicitly where a variable will be stored in memory, not least because many things are done by the operating system with respect to the memory itself (which results in the fact that the virtual memory mapping is not a fixed process).

However, nothing prevents you from initializing a pointer with a specific memory address:

volatile unsigned int *ponteiro = (volatile unsigned int *)0x000001;
/* volatile está sendo usado com o intuito de garantir que o valor passado ao ponteiro não
   seja uma cópia previamente possuída pelo programa, ou seja, garante que seu valor está
   sendo obtido diretamente da memória em cada acesso. */
  • In this case, if the address is a valid address, will it be allocated smoothly at this address? Can I do this with variables too or just pointers? I work with microcontrollers, I know that in Assembly it is possible to do this quietly. But I never did in C and that possibility attracted me very much. Grateful for your response.

  • 1

    In this case it must necessarily be a pointer because you are initiating it with a specific memory address (causing it to point to that place). If it’s a valid memory address, it can point there, but if you try to get a variable to be allocated to a fixed memory address, for example, then the system can either accept or reject, where the rejection occurs if a page containing that address has already been mapped.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.