Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 08-13-2019, 22:12
chants chants is online now
VIP
 
Join Date: Jul 2016
Posts: 723
Rept. Given: 35
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 665
Thanks Rcvd at 1,050 Times in 475 Posts
chants Reputation: 48
A Quiz in Advanced RE (Asm/C)

Just some interesting stuff for those interested. If anyone has their own, please share.

1) In what special circumstance is sizeof(ptr1) != sizeof(ptr2)?
2) Name the computer science algorithm which places type dependencies (typedefs) in a correct order. BONUS: how to minimize forward declarations (from structure pointer circular dependencies) and what is the complexity of the graph problem?
3) How are capture arguments of lambda functions dealt with in assembly, and with which calling convention is it effectively invoked?
4) What is the difference between parameters in a variadic function (…) verse one converted to use a va_list?
5) A recursive function has many parameters which are never changed, or even better has merely more than one argument and is using a lot of stack space, while not having an guarantee as to its depth limit. How to make this safe?

Code:
1) In compilers with compact and medium models where function pointers and data pointers could have near or far sizes. 2) Depth first search with post-order traversal, which keeps track of 3 colorings: visited (normal DFS single visit), resolved (to prevent cycles) and lastly the both unresolved/unvisited state. I don't have the answer to the bonus currently - my guess its an NP complete problem. 3) The capture arguments are turned into a data structure, and then this structure is constructed on the stack. The calling convention is basically the __thiscall calling convention as the structure and the function call are as if a class were initialized and its member function executed, just as the older functor class works. However, there is no construction/destruction and compiler optimizations make it slightly more efficient and advantageous. 4) va_list is merely a pointer to the first argument of the ellipsis in the simplest case which is incremented on consumption. Otherwise compiler and environment dependent, it becomes a pointer to a data structure describing the registers, stack, and current position. 5) Ideally, remove the recursion, make the unchanged variables local variables, and use a dynamic memory stack object such as std::stack, and push and pop the changing variables - taking special care for the pre-traversal (easier, always remove top) and post-traversal nuances of recursion (only remove top after all children recursed). Alternatively, create a class for the traversal, which makes the unchanged variables as member variables initialized via a constructor. Then combine all changing arguments into a data structure and make a single argument call which uses pointers to the data structure and member variables.

Last edited by chants; 08-13-2019 at 22:22.
Reply With Quote
The Following 3 Users Say Thank You to chants For This Useful Post:
computerline (08-14-2019), niculaita (08-13-2019), p4r4d0x (08-15-2019)
  #2  
Old 08-24-2019, 12:13
winndy winndy is offline
VIP
 
Join Date: Sep 2005
Posts: 236
Rept. Given: 104
Rept. Rcvd 26 Times in 12 Posts
Thanks Given: 27
Thanks Rcvd at 16 Times in 13 Posts
winndy Reputation: 26
hard to answer.
Just curious what's the percentage of interviewees that can answer the questions.

Anyway, thanks for share.
Reply With Quote
The Following User Says Thank You to winndy For This Useful Post:
chants (08-24-2019)
  #3  
Old 09-02-2019, 21:13
BlackWhite BlackWhite is offline
Friend
 
Join Date: Apr 2013
Posts: 80
Rept. Given: 4
Rept. Rcvd 14 Times in 6 Posts
Thanks Given: 12
Thanks Rcvd at 48 Times in 21 Posts
BlackWhite Reputation: 14
I think sizeof(ptr1) != sizeof(ptr2) is impossible.
Whether a ptr is void or NULL or even wild, its size must be equal to sizeof(unsigned int).
There is only one case I may have missed, that's far pointer compared with the near one.
Reply With Quote
The Following User Says Thank You to BlackWhite For This Useful Post:
chants (09-04-2019)
  #4  
Old 09-03-2019, 18:53
tom324 tom324 is offline
Friend
 
Join Date: Jan 2002
Posts: 231
Rept. Given: 5
Rept. Rcvd 7 Times in 6 Posts
Thanks Given: 21
Thanks Rcvd at 27 Times in 16 Posts
tom324 Reputation: 7
1) Pointers can point to different types of memory and not all CPU architectures are Von_Neumann_architecture

example Intel 8051 pointers

http://www.keil.com/support/man/docs...51_le_ptrs.htm
Reply With Quote
The Following User Says Thank You to tom324 For This Useful Post:
chants (09-04-2019)
  #5  
Old 09-03-2019, 20:47
zeffy zeffy is offline
Friend
 
Join Date: Jul 2017
Posts: 44
Rept. Given: 3
Rept. Rcvd 7 Times in 6 Posts
Thanks Given: 194
Thanks Rcvd at 163 Times in 47 Posts
zeffy Reputation: 7
1) At least with MSVC you can specify pointer size with __ptr32 and __ptr64 when building for 64-bit. https://docs.microsoft.com/en-us/cpp/cpp/ptr32-ptr64

3) I believe usually a temporary object is constructed using pointers to the lambda arguments, and the function is invoked using the __thiscall convention. Probably depends on the compiler's implementation though.

Had to check answer for the others Very interesting questions.
Reply With Quote
The Following User Says Thank You to zeffy For This Useful Post:
chants (09-04-2019)
  #6  
Old 09-04-2019, 00:36
chants chants is online now
VIP
 
Join Date: Jul 2016
Posts: 723
Rept. Given: 35
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 665
Thanks Rcvd at 1,050 Times in 475 Posts
chants Reputation: 48
For the first question for some more interesting detail (its very compiler specific of course), taken from StackOverflow
Quote:
https://stackoverflow.com/questions/1473935/can-the-size-of-pointers-vary-between-data-and-function-pointers
:
Quote:
> type ppp.c
#include <stdio.h>
#include <stdlib.h>

int global = 0;

int main(void) {
int local = 0;
static int staticint = 0;
int *mall;
int (*fx)(void);

fx = main;
mall = malloc(42); /* assume it worked */
printf("#sizeof pointer to local: %d\n", (int)sizeof &local);
printf("#sizeof pointer to static: %d\n", (int)sizeof &staticint);
printf("#sizeof pointer to malloc'd: %d\n", (int)sizeof mall);
printf("#sizeof pointer to global: %d\n", (int)sizeof &global);
printf("#sizeof pointer to main(): %d\n", (int)sizeof fx);
free(mall);
return 0;
}
> tcc -mc ppp.c
Turbo C Version 2.01 ...
warnings about unused variables elided ...
Turbo Link Version 2.0 ...
> ppp
#sizeof pointer to local: 4
#sizeof pointer to static: 4
#sizeof pointer to malloc'd: 4
#sizeof pointer to global: 4
#sizeof pointer to main(): 2
> tcc -mm ppp.c
> ppp
#sizeof pointer to local: 2
#sizeof pointer to static: 2
#sizeof pointer to malloc'd: 2
#sizeof pointer to global: 2
#sizeof pointer to main(): 4
tcc -mc generates code in the "compact" model; tcc -mm generates code in the "medium" model
I did not know about the __ptr32/64 but that's also quite interesting since in ASM, 64-bit often uses 32-bit relative displacements and not raw 64-bit addresses.

A pointer to a function pointer is data again too and so the function pointer is much more specific.

3) as far as I know its the captures that are on the temporary object, and the actual function arguments are passed per __thiscall logic.

I did not give any interviews with these questions but it would be interesting to see what creative answers people would come up with. Obviously these are a bit to technical and advanced to do more than probe and analyze people's knowledge a bit. Would be interesting to see them used for a "Senior Reverse Engineer" job or the like .
Reply With Quote
The Following User Says Thank You to chants For This Useful Post:
zeffy (09-05-2019)
  #7  
Old 09-05-2019, 05:50
zeffy zeffy is offline
Friend
 
Join Date: Jul 2017
Posts: 44
Rept. Given: 3
Rept. Rcvd 7 Times in 6 Posts
Thanks Given: 194
Thanks Rcvd at 163 Times in 47 Posts
zeffy Reputation: 7
Quote:
Originally Posted by chants View Post
3) as far as I know its the captures that are on the temporary object, and the actual function arguments are passed per __thiscall logic.
Oops, you're right. I knew that but mixed up the terminology (captures vs arguments), heh.

Here's an example of how MSVC seems to implement lambdas:

Code:
bool normal_function()
{
    int a, b, c;
    int d = 0;
    int e = 0;
    int f = 0;

    return [a, b, c](int, int, int) -> bool {
        return true;
    }(d, e, f);
}
Which is compiled into something resembling this:

Code:
bool normal_function()
{
    class lambda_class
    {
        int *a_;
        int *b_;
        int *c_;

    public:
        lambda_class(int *a, int *b, int *c)
            : a_(a), b_(c), c_(c)
        {
        }

        bool operator()(int d, int e, int f)
        {
            return true;
        }
    };

    int a, b, c;
    int d = 0;
    int e = 0;
    int f = 0;

    return lambda_class(&a, &b, &c)(d, e, f);
}
Reply With Quote
The Following User Says Thank You to zeffy For This Useful Post:
chants (09-05-2019)
  #8  
Old 09-05-2019, 14:36
chants chants is online now
VIP
 
Join Date: Jul 2016
Posts: 723
Rept. Given: 35
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 665
Thanks Rcvd at 1,050 Times in 475 Posts
chants Reputation: 48
Exactly right. The class you mention is originally known as a functor with the operator parenthesis.

And very notably though, lambdas are slightly more efficient. Because no class is truly constructed. The constructor you wrote is not actually called - it can be optimized out by the compiler. There is no constructor/destructor just copying capture values and invocation of the () method and of course the object is stack constructed not dynamically allocated.

A really thorough analysis is here:
Quote:
https://web.mst.edu/~nmjxv3/articles/lambdas.html
Useful conclusions:
Quote:
1. Functors and lambdas are always passed a this pointer, whereas plain functions naturally are not. This consumes an extra register and 8 bytes of stack space.
2. Lambda "constructors" are inlined into the function in which the lambda is created. This significantly reduces the amount of copying performed (2 instructions for lambdas, 5 for functors), as well as avoiding a function call setup and teardown.
Reply With Quote
The Following User Says Thank You to chants For This Useful Post:
zeffy (09-05-2019)
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



All times are GMT +8. The time now is 10:05.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( 1998 - 2024 )