Storing local variables in compiled object file - object

According to these answers, Where does initialized auto variables (local variables) placed in object file? and Where do local variables get stored at compile time?, initialized local variables in methods are not stored in the object file but I wonder how that is possible. I mean, if I have the next code, the value 4 has to be codified in the object file like a global initialized variable occupying its corresponding bytes. If it is not codified occupying its bytes, how the program loads the value 4 in the stack when this method is executed?.
void method(){
int number = 4;
}
Thanks!

Related

Anchor `declare_id!` with Environment Variable - Environment Variables in Macros

In anchor the "top" of any program features a declare_id!() statement. The input to that statement is a Pubkey, typically in the form of a hard coded string. 12Factor Methodology typically dictates that hard coded configuration values like this should be avoided. However trying to not hard code the value has me pulling out my hair.
declare_id!(std::env::var("VARIABLE_NAME"));
Does not work because the env::var call executes at runtime while the macro executes at compile time.
declare_id!(env!("VARIABLE_NAME"));
Does not work because env! returns a &str.
declare_id!(Pubkey::from_str(env!("VARIABLE_NAME")));
Does not work because Pubkey::from_str can fail and as such returns a Result
declare_id!(Pubkey::from_str(env!("VARIABLE_NAME")).unwrap());
Does not work because declare_id! requires a constant and constants cannot be made from unwrap (Its probably more nuanced than that, but I'm new to rust) and ? fails for the same reason.
How would I go about defining an environment variable within a macro?
Given the lack of resources on the topic, I'm presuming an environment variable in this case is not a best practice. Why should one not use an environment variable in this case?
How can one accomplish the injection of program id into an anchor application if environment variables are not the way to do so?
Bonus points:
env::var() returns a Result<&str>
env::var_os() returns a Result<&OsStr>
env!() returns a &str
env_os!() does not exist in core
How do you handle an OsStr environment variable at build time? Why would you not need to be able to?
Working with env vars seems troublesome, since most of the ways of creating a Pubkey aren't const fn. To me, this seems like an issue with the anchor-lang crate, usually env vars aren't this troublesome.
That said, you could write the key to a config file somewhere, and read that in using include_bytes, and pass that to Pubkey::new_from_array, which is const:
// this works because concat! expands to a string literal
const BYTES: &[u8; 32] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/key"));
anchor_lang::declare_id!(Pubkey::new_from_array(*BYTES));
If you don't want to store the file in the repo, you can point include_bytes!() at any location, even one read from an env var. For example, you could have:
const BYTES: &[u8; 32] = include_bytes!(env!("ANCHOR_KEY_LOCATION"));
anchor_lang::declare_id!(Pubkey::new_from_array(*BYTES));
which will read the key bytes from a file at $ANCHOR_KEY_LOCATION

How can I correctly create a new variable in vvar.h for my new VSDO func?

I am trying to declare a new variable in vvar.h and define it near my new VDSO function. So that I could use this variable in my vdso function.
I have a question about VVar. According to the description in arch/x86/include/asm/vvar.h, when I declare here a new variable as DECLARE_VVAR(0, int, count), I should use DEFINE_VVAR(type, name) to define this variable somewhere else.
The problem is after I defined this variable somewhere else, like DEFINE_VVAR(int, count), when I am trying to assign an integer value to this variable count, it is failed. This is because after kernel version 5.2 #define DEFINE_VVAR(type, name) has been changed from #define DEFINE_VVAR(type, name) type name to #define DEFINE_VVAR(type, name) type name[CS_BASES]. Right now this variable count is an integer array instead of type integer. Therefore I can't assign a integer value to it. Do you know how to fix it?
VVAR.h: https://elixir.bootlin.com/linux/v5.12/source/arch/x86/include/asm/vvar.h#L43
Typically, you cannot add a variable simply through DECLARE_VVAR macro.
The first thing you have to be aware of is that .vvar is a page of memory located inside the memory (more specifically, before .vdso) and could access by both kernel and userland. You can see this inside the linker script https://elixir.bootlin.com/linux/latest/source/arch/x86/entry/vdso/vdso-layout.lds.S. For now, kernel already has a data structure `struct video to format the data inside this page.
Second, assume you want to add a variable inside the .vvar page and access it in your new vdso function, the easiest way is to add it inside the sturct vdso structure of include/vdso/datapage.h: https://elixir.bootlin.com/linux/latest/source/include/vdso/datapage.h. After that, you can update them inside the kernel (for example, in schedule) in the same way as other vvar variables.
Second, if you want to own your own vvar page, you have to define your own vvar data structure inside the datapage.h and do not forget DEFINE_VVAR in vsyscall.h: https://elixir.bootlin.com/linux/latest/source/arch/x86/include/asm/vdso/vsyscall.h ALso, since the vvar memory layout is compact, you also need to allocate another page through linker script: https://elixir.bootlin.com/linux/latest/source/arch/x86/entry/vdso/vdso-layout.lds.S by change vvar_start = . - 4 * PAGE_SIZE; into vvar_start = . - 5 * PAGE_SIZE;

Passing argument to lua function after evaluating function in string

I have functions process and matrix. The following code works
process(matrix({{2,4,6},{8,10,12},{14,16,20}}))
However the following doesn't work.
n='matrix({{2,4,6},{8,10,12},{14,16,20}})'
process(n)
It throws some error. The reason is obvious that process takes n as string rather than the output of the function matrix. So the basic difficulty involved here is about evaluating string from variable n and then give it as argument to the function process. Here loadstring function is of no use as matrix is local function and can't be referred from loadstring.
Is there any work around for this? I hope that I have clearly stated the problem here. It is about evaluating (or unloading) string and then passing it as argument to another function. Any help will be appreciated. Thanks.
as matrix is local function
Lua takes local declarations seriously. If a variable is declared local, it can only be accessed by code which is statically within the local scope of that variable. Strings which you later turn into code are not statically in the local scope and therefore cannot access local variables.
Now, with Lua 5.2+, you can provide load with a second parameter, a table which represents the global environment against which that Lua chunk will be built. If that table contains a matrix value, then the loaded string can access it. For Lua 5.1, you'd have to use setfenv on the function returned to load to accomplish a similar effect. The Lua 5.2+ method would look like this:
local env = {matrix = matrix}
local func = load("return matrix({{2,4,6},{8,10,12},{14,16,20}})", nil, "t", env)
process(func())
Note the following:
You must create an explicit table which is the global environment. There's nothing you can pass that says "make my locals available"; you have to put every local you'd like to access there. Which is, generally speaking, why you pass these things as parameters or just make them globals.
You explicitly need the "return " there if you want to get the results of the call to matrix.
You have to call the function. Functions are values in Lua, so you can freely pass them around. But if you want to pass the results of a function to another function, you have to actually call it.

Lua: returning or storing REPL/loadstring string output in a string variable

The same question already asked here
Lua: Executing a string and storing the output of the command in a variable
But I want the function loadstring somehow return the result in string form that may be assigned to a string variable later to use further, what it returns is a function.
Below code is an example:
ret = assert(loadstring(str_cmd))()
ret is a function:(
How can I get the REPL/loadstring output in string form?
If all output from str_cmd comes from calls to print, redefine print before loading str_cmd to save all output in a table. After running str_cmd, use the table in table.concat for instance.
Instead of redefining print you can provide an environment to run str_cmd in. You'll probably need to make that environment inherit from the global environment.

gdb watchpoint on struct variables

I have a structure like this :
struct A
{
int a;
char b;
};
this structure is referenced at various places in a large code. The pointer to this struct is passed on to different functions and accordingly the variables in this structure are updated. i want to set a watchpoint on variable a in this struct as it travels across many functions. to see how a changes. How do I set this watch point ?
First set a breakpoint where you create an instance of your struct using break, like
break myfile.c:9
Then just use watch to set a watchpoint, like
watch myStructInstance.a
for variable a or
watch *0x7ffff75177f0
for a memory address. The memory address can be obtained easily by using print, like
print &myStructInstance.a
Now every time variable a or the given memory address gets modified gdb will break.
I come with the same problem when debugging my virtual memory simulator. The problem is how to keep a close look at the data inside structs.
I tried using print to check, but that's too noisy. Because I have to print out more than 15 variables.
I also tried using watchpoint, but on my machine, I can only set no more than 4 hardware watchpoints. That's not even close to my goal.
Finally, I find my solution by using user-defined function in .gdbinit file. e.g. if I want to watch array of my structure, using
define lookintoStructs
if mystruct != 0x0
print mystruct[0]
print mystruct[1]
print mystruct[2]
print mystruct[3]
print mystruct[4]
print mystruct[5]
end
end
to make it more convenient to use, I'd like to make it hook to my next instruction in gdb.
define hook-next
lookintoStructs
end
so when I call next or n in gdb, lookintoStructs could be called automatically. works fine for me.

Resources