I want to assign some value (say 2345) to a memory location(say 0X12AED567). Can this be done?
In other words, how can I implement the following function?
void AssignValToPointer(uint32_t pointer, int value)
{
}
The fact that you are asking this question kind of indicates that you're in over your head. But here you go:
*(int *)0x12AED567 = 2345;
The answer depends on some factors. Is your program running on an operating system? If yes, does the OS implement memory segmentation?
If you answered yes to both questions, trying to access a memory area that is not mapped or that it doesn't have permission to write will cause a memory access violation (SIGSEGV on POSIX based systems). To accomplish that, you have to use a system specific function to map the region of memory that contains this exact address before trying to access it.
Just treat the memory location as a pointer
int* pMemory = OX12AED567;
*pMemory = 2345;
Note: This will only work if that memory location is accessible and writable by your program. Writing to an arbitrary memory location like this is inherently dangerous.
C99 standard draft
This is likely not possible without implementation defined behavior.
About casts like:
*(uint32_t *)0x12AED567 = 2345;
the C99 N1256 standard draft "6.3.2.3 Pointers" says:
5 An integer may be converted to any pointer type. Except as previously specified, the
result is implementation-defined, might not be correctly aligned, might not point to an
entity of the referenced type, and might be a trap representation. 56)
GCC implementation
GCC documents its int to pointer implementation at: https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Arrays-and-pointers-implementation.html#Arrays-and-pointers-implementation
A cast from integer to pointer discards most-significant bits if the pointer representation is smaller than the integer type, extends according to the signedness of the integer type if the pointer representation is larger than the integer type, otherwise the bits are unchanged.
so the cast will work as expected for this implementation. I expect other compilers to do similar things.
mmap
On Linux you can request allocation of a specific virtual memory address](How does x86 paging work?) with the first argument of mmap, man mmap reads:
If addr is NULL, then the kernel chooses the (page-aligned) address at which to create the mapping; this is the most portable method of creating a new mapping. If addr is not NULL, then the kernel takes it as a hint about where to place the mapping; on Linux, the kernel will pick a nearby page boundary (but always above or equal to the value specified by /proc/sys/vm/mmap_min_addr) and attempt to create the mapping there. If another mapping already exists there, the kernel picks a new address that may or may not depend on the hint. The address of the new mapping is returned as the result of the call.
So you could request for an address and assert that you got what you wanted.
As far as C is concerned, that's undefined behaviour. My following suggestion is also undefined behaviour, but avoids all the type-based and aliasing-based problems: Use chars.
int a = get_value();
char const * const p = (const char * const)&a;
char * q = (char *)0x12345;
memcpy(q, p, sizeof(int));
Alternatively, you can access bytes q[i] directly. (This is the part that is UB: the pointer q was not obtained as the address-of an actual object or as the result of an allocation function. Sometimes this is OK; for instance if you're writing a free-standing program that runs in real mode and accesses the graphics hardware, you can write to the graphics memory directly at a well-known, hard-coded address.)
You've indicated, that the address is a physical address, and that your code is running in a process.
So if you're
in kind of high level operating system, e.g. Linux, you'd have to get a mapping into the physical address space. In Linux, /dev/mem does that for you.
within the kernel or without operating system and with a MMU, you have to translate the physical address into a virtual address. In the Linux kernel, phys_to_virt() does that for you. In the kernel, I assume, this address is always mapped.
within the kernel or without operating system and without MMU, you write directly to that address. There's no mapping to consider at all.
Now, you have a valid mapping or the physical address itself, that you pass to your function.
void AssignValToPointer(uint32_t pointer, int value)
{
* ((volatile int *) pointer) = value;
}
You might want to add the volatile keyword as the compiler might optimize the write-operation away if you do not read from that location afterwards (likely case when writing to a register of a memory-mapped hardware).
You might also want to use the uintptr_t data type instead of uint32_t for the pointer.
With the proviso that it's not portable or safe (at all):
*((int *)0x12AED567) = 2345;
Related
Is it possible to allocate a single byte of memory at a specific desired address, say 0x123?
This suggests follow up questions:
Is it possible to know if a specific address has already been malloced?
Some complications could be:
The byte at the desired address 0x123 was already malloc'ed. In this case, can I move the byte value elsewhere and notify the compiler (or whatever's keeping track of these things) of the new address of the byte?
The byte at the desired address 0x123 was malloc'ed along with other bytes. E.g. char *str = malloc(8); and str <= 0x123 < str + 8, or in other words, 0x123 overlaps some portion of already malloc'ed memory. In this case, is it possible to move the portion of malloc'ed memory elsewhere and notify the compiler (or whatever's keeping track of these things)?
There are also several variations:
Is this possible if the desired address is known at compile time?
Is this possible if the desired address is known at run time?
I know mmap takes a hint addr, but it allocates in multiples of the pagesize and may or may not allocate at the given hint addr.
It is possible to assign a specific value to a pointer as follows:
unsigned char *p = (unsigned char *)0x123;
However dereferencing such a pointer will almost certainly result in undefined behavior on any hosted system.
The only time such a construct would be valid is on an embedded system where it is allowed to access an arbitrary address and the implementation documents specific addresses for specific uses.
As for trying to manipulate the inner workings of a malloc implementation, such a task is very system specific and not likely to yield any benefit.
The are operating-system-specific ways to do this. On Windows, you can use VirtualAlloc (with the MEM_COMMIT | MEM_RESERVE flags). On Linux, you can use mmap (with the MAP_FIXED_NOREPLACE flag). These are the operating system functions which give you full control over your own address space.
In either case, you can only map entire pages. Addresses only become valid and invalid a page at a time. You can't have a page that is only half valid, and you can't have a page where only one address is valid. This is a CPU limitation.
If the page you want is already allocated, then obviously you can't allocate it again.
On both Windows and Linux, you can't allocate the first page. This is so that accesses to NULL pointers (which point to the first page) will always crash.
Is it possible to allocate a single byte of memory at a specific desired address, say 0x123?
Generally: no. The C language doesn't cover allocation at specific addresses, it only covers how to access a specific address. Many compilers do provide a non-standard language extensions for how to allocate at a fixed address. When sticking to standard C, the actual allocation must either be done:
In hardware, by for example having a MCU which provides a memory-mapped register map, or
By the system-specific linker, through custom linker scripts.
See How to access a hardware register from firmware? for details.
malloc doesn't make any sense in either case, since it exclusively uses heap allocation and the heap sits inside a pre-designated address space.
For some reason, I want to get the address ranges of a stack. For example, consider the following example:
int main(){
int a = 0;
int b = 0;
}
Is there any generic way I can know the address of a and b (and another other variable on stack), without explicitly use &a in code?
Thanks!
Memory address in general, and stacks in particular, are system specific. There exists no way to obtain such information in standard C, nor is there a way to set the stack pointer in C.
In fact if you don't use the & operator, the variables are quite likely to get allocated in registers instead of the stack.
For the rare case where you actually need to know the stack address, for example when dealing with low level embedded systems, you'd typically go check a linker script and hardcode the value, or use some specific non-standard compiler extension.
I'm working on an embedded mcu that has two cores which can both see an area of memory beginning at 0x80000000.
The ADC is connected to one core and a radio is connected to another. I want to write the data value received by the ADC to this memory address so that the other core can read it.
Would somebody be able to help me figure out how to do this? The is no micro OS, it is bare metal.
Would I create a pointer to struct at a specific address?
I have two values in an array, how would I get them into the struct?
#define NUM_SAMPLES_POLLED (2)
uint16_t samples_polled[NUM_SAMPLES_POLLED]
In this case you'd assign the address directly to a pointer:
char *memdata = (char *)0x80000000;
Keep in mind that this behavior is implementation defined.
How can I create an array at this exact address with some values?
The C language does not define any mechanism for assigning variables to specific addresses. Indeed, no such mechanism would likely be viable in a hosted C implementation, for substantially all modern hosted implementations rely on an underlying OS with virtual memory.
Inasmuch as you are presumably writing for a freestanding implementation (given that the target is an embedded MCU), it is likely that there is a mechanism for what you ask. The one suggested by #dbush would then be a good candidate, but only by checking your documentation can you be sure.
It would be better to read your tool-chain's documentation on defining and using shared memory.
Array is not an object. Array in "c" is just a representation of data. so you cannot create it or destroy(or release it). you can just access it, i.e read and/or write.
void* ptr=(void*)0x80000000;
int* arr_of_int = (int*)ptr; //access memory location as array of int
arr_of_int[0] = 0x100; //write value to your array
int i = arr_of_int[10] ; // read value from array
or
char* arr_of_char = (char*)ptr; // access memory as array of char
arr_of_char[0] = 'A';
you have to make sure that you are actually allowed to access this address from with in your program as OS kernel(if you are running code as user program) will forbid direct physical addressing. In that case you need to use address translation function to calculate virtual address corresponding to physical address.
I'm a new C programmer, still learning the language itself.
Anyway -
I'm trying to access a specific memory address.
I've written this code:
#include <stdio.h>
int main()
{
int* p = (int*) 0x4e0f68;
*p = 12;
getchar();
}
When I try to access a specific memory address like that, the program crashes.
I don't know if this information is relevant, but I'm using Windows 7 and Linux Ubuntu.
(I've tried this code only on Windows 7).
Any explanations why the program crashes?
How can I access a specific memory address (an address which is known at compile-time, I don't mean to dynamic memory allocation)?
Thanks.
That's memory you don't own and accessing it is undefined behavior. Anything can happen, including crashing.
On most systems, you'd be able to inspect the memory (although technically still undefined behavior), but writing to it is a whole different story.
Strictly speaking you cannot create a valid pointer like this. Valid pointers must point to valid objects (either on your stack or obtained from malloc).
For most modern operating systems you have a virtual memory space that only your process can see. As you request more memory from the system (malloc, VirtualAlloc, mmap, etc) this virtual memory is mapped into real usable memory that you can safely read and write to. So you can't just take an arbitrary address and try to use it without OS cooperation.
An example for windows:
#include <windows.h>
#include <stdio.h>
int main(void)
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
unsigned pageSize = sysinfo.dwPageSize;
printf("page size: %d\n", pageSize);
void* target = (void*)0x4e0f68;
printf("trying to allocate exactly one page containing 0x%p...\n", target);
void* ptr = VirtualAlloc(target, pageSize, MEM_COMMIT, PAGE_READWRITE);
if (ptr)
printf("got: 0x%p\n", ptr); // ptr <= target < ptr+pageSize
else
printf("failed! OS wont let us use that address.\n");
return 0;
}
Note that this will give you different results on different runs. Try it more than once.
Just to clrify one phrase the OP wrote: strictly speaking, no address associated to a program (code or data) is known at compile time. Programs usually are loaded at whatever address the OS determines. The final address a program sees (for example, to read a global variable) is patched by the OS in the very program code, using some sort of relocation table. DLL functions called by a program have a similar mechanism, where the IDATA section of the executable is converted into a jump table to jump to the actual address of a function in a DLL, taking the actual addresses from the DLL in memory.
That said, it is indeed possible to know by advance where a variable will be placed, if the program is linked with no relocation information. This is possible in Windows, where you can tell the linker to load the program to an absolute virtual address. The OS loader will try to load your program to that address, if possible.
However, this feature is not recommended because it can lead to easily exploiting possible security holes. If an attacker discovers a security hole in a program and try to inject code into it, it will be easier for him if the program has all its variables and functions in specific addresses, so the malicious code will know where to make patches to gain control of that program.
What you're getting is a segfault - when you're trying to access memory you don't have permission to access. Pointers, at least for userspace, must point to some variable, object, function, etc. You can set a pointer to a variable with the & operator - int* somePtr = &variableToPointTo, or to another pointer - int* someNewPtr = somePtr. In kernel mode (ring 0) or for OS development, you can do that, BUT IT IS NOT ADVISED TO DO SO. In MS-DOS, you could destroy your machine because there was no protection against that.
Working my way through a C tutorial
#include <stdio.h>
int main() {
short s = 10;
int i = *(int *)&s; // wonder about this
printf("%i", i);
return 0;
}
When I tell C that the address of s is an int, should it not read 4 bytes?
Starting from the left most side of 2 bytes of s. In which case is this not critically dangerous as I don't know what it is reading since the short only assigned 2 bytes?
Should this not crash for trying to access memory that I haven't assigned/belong-to-me?
Don't do that ever
Throw away the tutorial if it teaches/preaches that.
As you pointed out it will read more bytes than that were actually allocated, so it reads off some garbage value from the memory not allocate by your variable.
In fact it is dangerous and it breaks the Strict Aliasing Rule[Detail below] and causes an Undefined Behavior.
The compiler should give you a warning like this.
warning: dereferencing type-punned pointer will break strict-aliasing rules
And you should always listen to your compiler when it cries out that warning.
[Detail]
Strict aliasing is an assumption, made by the C (or C++) compiler, that dereferencing pointers to objects of different types will never refer to the same memory location (i.e. alias each other.)
The exception to the rule is a char*, which is allowed to point to any type.
First of all, never do this.
As to why it doesn't crash: since s is a local, it's allocated on the stack. If short and int have different sizes in your architecture (which is not a given), then you will probably end up reading a few more bytes from memory that's on the same memory page as the stack; so and there will be no access violation (even though you will read garbage).
Probably.
This is dangerous and undefined behaviour, just as you said.
The reason why it doesn't crash on 32 (or 64) bit platforms is that most compilers allocate atleast 32 bits for each stack variable. This makes the access faster, but on e.g. 8 bit processor you would get garbage data in the upper bits instead.
No it's not going to crash your program, however it is going to be reading a portion of other variables (or possibly garbage) on the stack. I don't know what tutorial you got this from, but that kind of code is scary.
First of all, all addresses are of the same size and if you're in a 64bit architecture, each char *, short * or int * will have 8 bytes.
When using a star before an ampersand it will cancel the effect, so *&x is semantically equivalent to just x.
Basically you are right in the sense that since you are accessing an int * pointer, this will fetch 4 bytes instead of the only 2 reserved for 's' storage and the resulting content won't be a perfect reflection of what 's' really means.
However this most likely won't crash since 's' is located on the stack so depending on how your stack is laid out at this point, you will most likely read data pushed during the 'main' function prologue...
See for a program to crash due to invalid read memory access, you need to access a memory region that is not mapped which will trigger a 'segmentation fault' at the userworld level while a 'page fault' at the kernel level. By 'mapped' I mean you have a known mapping between a virtual memory region and a physical memory region (such mapping is handled by the operating system). That is why if you access a NULL pointer you will get such exception because there is no valid mapping at the userworld level. A valid mapping will usually be given to you by calling something like malloc() (note that malloc() is not a syscall but a smart wrapper around that manages your virtual memory blocks). Your stack is no exception since it is just memory like anything else but some pre-mapped area is already done for you so that when you create a local variable in a block you don't have to worry about its memory location since that's handled for you and in this case you are not accessing far enough to reach something non-mapped.
Now let's say you do something like that:
short s = 10;
int *i = (int *)&s;
*i = -1;
Then in this case your program is more likely to crash since in this case you start overwriting data. Depending on the data you are touching the effect of this might range from harmless program misbehavior to a program crash if for instance you overwrite the return address pushed in the stack... Data corruption is to me one of the hardest (if not the hardest) bugs category to deal with since its effect can affect your system randomly with non-deterministic pattern and might happen long after the original offending instructions were actually executed.
If you want to understand more about internal memory management, you probably want to look into Virtual Memory Management in Operating System designs.
Hope it helps,