I'm using IDebugSymbols::GetNameByOffset and I'm finding that I get the same symbol name for different functions that overload the same name.
E.g. The code I'm looking up the symbols for might be as follows:
void SomeFunction(int) {..}
void SomeFunction(float) {..}
At runtime, when I have an address of an instruction from each of these functions I'd like to use GetNameByOffset and tell the two apart somehow. I've experimented with calling SetSymbolOptions toggling the SYMOPT_UNDNAME and SYMOPT_NO_CPP flags as documented here, but this didn't work.
Does anyone know how to tell these to symbols apart in the debugger engine universe?
Edit: Please see me comment on the accepted answer for a minor amendment to the proposed solution.
Quote from dbgeng.h:
// A symbol name may not be unique, particularly
// when overloaded functions exist which all
// have the same name. If GetOffsetByName
// finds multiple matches for the name it
// can return any one of them. In that
// case it will return S_FALSE to indicate
// that ambiguity was arbitrarily resolved.
// A caller can then use SearchSymbols to
// find all of the matches if it wishes to
// perform different disambiguation.
STDMETHOD(GetOffsetByName)(
THIS_
__in PCSTR Symbol,
__out PULONG64 Offset
) PURE;
So, I would get the name with IDebugSymbols::GetNameByOffset() (it comes back like "module!name" I believe), make sure it is an overload (if you're not sure) using IDebugSymbols::GetOffsetByName() (which is supposed to return S_FALSE for multiple overloads), and look up all possibilities with this name using StartSymbolMatch()/EndSymbolMatch(). Not a one liner though (and not really helpful for that matter...)
Another option would be to go with
HRESULT
IDebugSymbols3::GetFunctionEntryByOffset(
IN ULONG64 Offset,
IN ULONG Flags,
OUT OPTIONAL PVOID Buffer,
IN ULONG BufferSize,
OUT OPTIONAL PULONG BufferNeeded
);
// It can be used to retrieve FPO data on a particular function:
FPO_DATA fpo;
HRESULT hres=m_Symbols3->GetFunctionEntryByOffset(
addr, // Offset
0, // Flags
&fpo, // Buffer
sizeof(fpo), // BufferSize
0 // BufferNeeded
));
and then use fpo.cdwParams for basic parameter size discrimination (cdwParams=size of parameters)
Related
Reference:
boost_1_78_0/doc/html/boost_asio/reference/ip__basic_resolver/async_resolve/overload1.html
template<
typename ResolveHandler = DEFAULT>
DEDUCED async_resolve(
const query & q,
ResolveHandler && handler = DEFAULT);
The handler to be called when the resolve operation completes. Copies
will be made of the handler as required. The function signature of the
handler must be:
void handler(
const boost::system::error_code& error, // Result of operation.
resolver::results_type results // Resolved endpoints as a range.
);
boost_1_78_0/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp
void run(char const *host, char const *port, char const *text) {
...
resolver_.async_resolve(
host, port,
beast::bind_front_handler(&session::on_resolve, shared_from_this()));
}
void on_resolve(beast::error_code ec, tcp::resolver::results_type results) {
if (ec)
return fail(ec, "resolve");
// Set a timeout on the operation
beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
// Make the connection on the IP address we get from a lookup
beast::get_lowest_layer(ws_).async_connect(
results,
beast::bind_front_handler(&session::on_connect, shared_from_this()));
}
Question 1> Why does the on_resolve use the following function signature?
on_resolve(beast::error_code ec, tcp::resolver::results_type results)
As shown above, the first parameter(i.e. ec) is taken as pass-by value. This happens almost in all other functions which take a beast::error_code as an input parameter within sample code.
Instead of
on_resolve(const beast::error_code& ec, tcp::resolver::results_type results)
Question 2> Why doesn't the documentation suggest using the following instead?
on_resolve(const beast::error_code& ec, const tcp::resolver::results_type& results)
Thank you
It's a cultural difference between Asio and Beast if you will.
UPDATE
There's some contention about my initial response.
It turns out that at least Boost System's error_code recently got endowed with shiny new (non-standard) features, that makes it bigger. Perhaps big enough to make it more efficient to pass by reference.
In the words of Vinnie Falco: This needs to be studied again.
Rationale
In Asio, the standard "doctrine" is to take error_code by const&. In Beast, the standard practice is actually to pass by value, which is, IMO, how error_code is intended.
In essence, error_code is just a tuple of (int, error_category const*) which is trivially copied and therefore optimized. Passing by value allows compilers much more room for optimization, especially when inlining. A key factor is that value-arguments never create aliasing opportunities.
(I can try to find a reference as I think some Beast devs are on record explaining this rationale.)
Why is it OK?
Any function that takes T by value is delegation-compatible with the requirement that it takes T by const reference, as long as T is copyable.
Other thoughts
There may have been historical reasons why Asio preferred, or even mandated error_code const& in the past, but as far as I am aware, any of these reasons are obsolete.
I'm still learning C++, and I'm doing some API work, but I'm, having trouble parsing this pointer arrangement.
void* data;
res = npt.receive(0x1007, params, 1, response, (void**)&data, size);
uint32_t* op = (uint32_t*)data;
uint32_t num = *op;
op++;
Can anyone explain what is going on with that void pointer? I see it being defined, it does something in the res line(maybe initialized?), then it's copied to an uint32 pointer, and dereferenced in num. Can anyone help me parse the (void**)&data declaration?
Pay attention when you use the void pointer:
The void type of pointer is a special type of pointer. In C++, void represents the absence of type. Therefore, void pointers are pointers that point to a value that has no type (and thus also an undetermined length and undetermined dereferencing properties).
This gives void pointers a great flexibility, by being able to point to any data type, from an integer value or a float to a string of characters. In exchange, they have a great limitation: the data pointed to by them cannot be directly dereferenced (which is logical, since we have no type to dereference to), and for that reason, any address in a void pointer needs to be transformed into some other pointer type that points to a concrete data type before being dereferenced.
From C++ reference
Firstly: What is npt?
Secondly: Guessing what npt could be some explanation:
// Declare a pointer to void named data
void* data;
// npt.receive takes as 5th parameter a pointer to pointer to void,
// which is why you provide the address of the void* using &data.
// The void ** appears to be unnecessary unless the data type of the
// param is not void **
// What is "npt"?
res = npt.receive(0x1007, params, 1, response, (void**)&data, size);
// ~.receive initialized data with contents.
// Now make the uint32_t data usable by casting void * to uint32_t*
uint32_t* op = (uint32_t*)data;
// Use the data by dereferencing it.
uint32_t num = *op;
// Pointer arithmetic: Move the pointer by sizeof(uint32_t).
// Did receive fill in an array?
op++;
Update
Signature of receive is:
<whatever return type> receive(uint16_t code, uint32_t* params, uint8_t nparam, Container& response, void** data, uint32_t& size)
So the data parameter is of type void** already so the explicit type cast to void** using (void**) is not necessary.
Considering the usage, the received data appears to be an array of uint32_t values IN THIS CASE!
Void as a type means no type and no type information regarding size and alignment is available, but is mandatory for lexical and syntactical consistency.
In conjunction with the *, it can be used as a pointer to data of unknown type and must be explicitly cast to another type (adds type information) before any use.
You usually have a void* or void** in an API, if you dont know the specific data type or only received plain byte data.
To understand this please read up C type erasure using void*
Please read up as basics before:
Dynamically allocated C arrays.
Pointers and Pointer Arithmetics.
From the code, ntp.receive tells you whether it receives anything successfully in the return code but it also needs to give you what it receives. It has a pointer that it wants to pass back, so you have to tell it where that pointer is so that it can fill it, hence (void **), a pointer to a pointer, being the address of your pointer, &data.
When you have received it, you know as the developer that what it points to is actually a uint_32 value so you copy the void pointer into one that points to a uint_32. In fact, this step is unnecessary since you could have cast the uint_32 pointer to void** in the above call but we'll let that slide.
Now that you have told the compiler that the pointer points to a 32 bit number, you can take the number on the other end of that pointer (*op) and store it in a local variable. Again, unnecessary, as *op could be used anywhere num is subsequently used.
Hope this helps.
i have problem with this code:
int
WINAPI
Getdesc(IN WORD wcode,
OUT LPWSTR lpBuf)
{
WCHAR szDescription[256];
int res = LoadStringW(NULL,wcode,szDescription,256);
if(res == 0)
{
wcscpy(lpBuf, L"Undefined");
return 0;
}
else
{
wcscpy(lpBuf,szDescription);
return 0;
}
}
The function is placed in a DLL, and when i access it, it always returns "Undefined",
I think there is problem in my LoadString call, but i can't figure it out.
I'm new to windows programming, any help would be appreciated
The problem is that you are passing NULL as the HINSTANCE parameter. That means that you look for the resource in the executable host and not the DLL. You'll have to pass the module handle of the DLL. You are provided with that instance handle as the first parameter passed to your DllMain function.
If you are compiling with MSVC then you could use __ImageBase to obtain the module handle. Personally I would suggest that making a note of the value passed to DllMain is a cleaner approach. It avoids taking a dependency on one specific compiler.
Note also that you can call GetLastError in case LoadString fails to obtain more information about the reason for the error. It's quite possible that would have helped you identify the fault.
Windows allows the creation of (named) Event objects.
An Event (the synchronization primitive in Windows) can be of type auto-reset (in which case you could say it's kind of a semaphore) or it can be of type manual-reset in which case it remains set until someone resets it.
Now, from the docs for CreateEvent, OpenEvent, SetEvent, etc. it does seem that there is no way to determine, once the event has been created, whether it's auto-reset or maual-reset.
I am in the situation, where one process creates a named Event and a 2nd process will have to operate on this event (it gets passed the name and then'll open the event and eventually signal it). Since the event should always be a manual-reset event for the whole thing to make sense, I would have liked to add a check in the 2nd process to make sure it is a manual-reset event. Is there any way to check for this?
(And yes, it's more of a nice-to-have in my situation, as it would be a bug anyway if any code would create a auto-reset event and then pass it to this process. But bugs happen, and the better if I can detect them.)
There's no documented way to do this, but it's actually not hard if you venture into undocumented land. (For your purposes, this should be fine since it doesn't really affect your program's functionality.)
The first thing you need to do is figure out if the handle given to you is an event or not. You use NtQueryObject for this. The function is documented here: http://msdn.microsoft.com/en-us/library/bb432383(v=vs.85).aspx. It comes with the usual provisios for native APIs that it might disappear or change without notice. Partial example:
#include <winternl.h>
typedef NTSTATUS (NTAPI * PFN_NtQueryObject)(
HANDLE Handle,
OBJECT_INFORMATION_CLASS ObjectInformationClass,
PVOID ObjectInformation,
ULONG ObjectInformationLength,
PULONG ReturnLength );
HMODULE ntdll = GetModuleHandle( L"ntdll.dll" );
auto NtQueryObject = (PFN_NtQueryObject)GetProcAddress( ntdll, "NtQueryObject" );
NTSTATUS result = NtQueryObject(
eventHandle,
ObjectTypeInformation,
buffer,
length,
&length );
This will give you a PUBLIC_OBJECT_TYPE_INFORMATION structure. The TypeName field will be "Event" if the object is actually an event.
Next, you call NtQueryEvent to get the event's type. All this is completely undocumented.
typedef enum _EVENT_INFORMATION_CLASS {
EventBasicInformation
} EVENT_INFORMATION_CLASS, *PEVENT_INFORMATION_CLASS;
typedef enum _EVENT_TYPE {
NotificationEvent,
SynchronizationEvent
} EVENT_TYPE, *PEVENT_TYPE;
typedef struct _EVENT_BASIC_INFORMATION {
EVENT_TYPE EventType;
LONG EventState;
} EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION;
typedef NTSTATUS (NTAPI * PFN_NtQueryEvent)(
HANDLE EventHandle,
EVENT_INFORMATION_CLASS EventInformationClass,
PVOID EventInformation,
ULONG EventInformationLength,
PULONG ReturnLength );
auto NtQueryEvent = (PFN_NtQueryEvent)GetProcAddress( ntdll, "NtQueryEvent" );
EVENT_BASIC_INFORMATION info;
ULONG length = sizeof( info );
NTSTATUS result = NtQueryEvent(
eventHandle,
EventBasicInformation,
&info,
length,
&length );
Now, just examine the EventType field in the info and you're done. "NotificationEvent" means manual reset and "SynchronizationEvent" means auto reset.
If you're wondering how I figured that second part out, I didn't. The information comes from here: http://undocumented.ntinternals.net/. Please use responsibly!
Call WaitForSingleObject( handle, 0 ) immediately after your initial WaitForSingleObject has returned. If the return value is WAIT_TIMEOUT then you know it is an auto-reset event, if it is WAIT_OBJECT_0 will be returned and it is a manual reset event.
This does rely on the handle being set in-between the two calls, so there is a potential race condition where it does not detect an auto-reset event, but it should work most of the time. As it is a nice-to-have, hopefully that is enough?
I would like to use MS function to send data.
I didnt find examples where they send other type of data other than const char * .
I tried to send a int, or other, but I failed.
WSASend() and send() both function only take a Char* parameters.
How should i proceed ?
Thanks
Its just a pointer to a buffer, this buffer may contains anything you want.
This char pointer is actually an address to a bytes array, this function requires a length parameter too.
An integer is a 2/4 (short/long) bytes value,
Then if you want to send an integer variable (for example) you have to pass its address, and its length.
WSASend and send are simple functions that send a memory block.
I assume you are talking about C, you have to understand that C's char variables are bytes - 8 bits block, char variables contain any value between 0 and 255.
A pointer to a char var is an address to a byte (which maybe the first cell of a bytes array).
I think thats what confuses you.
I hope you understand.
The const char* parameter indicates that the function is taking a pointer to bytes. Witch really seems to be the result of the original socket api designers being pedantic - C has a generic type to handle any kind of pointer without explicit casts: void*.
You could make a convenience wrapper for send like this - which would allow you to send any (contiguous) thing you can make a pointer to:
int MySend(SOCKET s, const void* buf, int len,int flags)
{
return send(s,(const char*)buf,len,flags);
}
Using void* in place of char* actually makes the api safer, as it can now detect when you do something stupid:
int x=0x1234;
send(s,(const char*)x,sizeof(x),0); // looks right, but is wrong.
mysend(s,x,sizeof(x),0); // this version correctly fails
mysend(s,&x,sizeof(x),0); // correct - pass a pointer to the buffer to send.
WSASend is a bit more tricky to make a convenience wapper for as you have to pass it an array of structs that contain the char*'s - but again its a case of defining an equivalent struct with const void*'s in place of the const char*'s and then casting the data structures to the WSA types in the convenience wrapper. Get it right once, and the rest of the program becomes much easier to determine correct as you don't need casts everywhere hiding potential bugs.