How to Get the Build Uuid in Runtime and the Image Base Address

How to get the build UUID in runtime and the image base address

Here is a solution similar to Kerni's answer but which works for any platform (iOS device + simulator and OS X) and any architecture (32-bit + 64-bit). It also returns a NSUUID instead of a NSString.

#import <mach-o/dyld.h>
#import <mach-o/loader.h>

static NSUUID *ExecutableUUID(void)
{
const struct mach_header *executableHeader = NULL;
for (uint32_t i = 0; i < _dyld_image_count(); i++)
{
const struct mach_header *header = _dyld_get_image_header(i);
if (header->filetype == MH_EXECUTE)
{
executableHeader = header;
break;
}
}

if (!executableHeader)
return nil;

BOOL is64bit = executableHeader->magic == MH_MAGIC_64 || executableHeader->magic == MH_CIGAM_64;
uintptr_t cursor = (uintptr_t)executableHeader + (is64bit ? sizeof(struct mach_header_64) : sizeof(struct mach_header));
const struct segment_command *segmentCommand = NULL;
for (uint32_t i = 0; i < executableHeader->ncmds; i++, cursor += segmentCommand->cmdsize)
{
segmentCommand = (struct segment_command *)cursor;
if (segmentCommand->cmd == LC_UUID)
{
const struct uuid_command *uuidCommand = (const struct uuid_command *)segmentCommand;
return [[NSUUID alloc] initWithUUIDBytes:uuidCommand->uuid];
}
}

return nil;
}

Given a mach_header how do I find the binary image name?

An answer, but possibly not the answer is the following:

// Required header:
#include <dlfcn.h>

// This is the callback, added via _dyld_register_func_for_add_image()
void add_binary_image(const struct mach_header *header, intptr_t slide)
{
// ...

Dl_info DlInfo;
dladdr(header, &DlInfo);
const char* image_name = DlInfo.dli_fname;

// ...
}

The docs state that the dladdr() function is available only in dynamically linked programs. The framework I wish to use this in also exists as a static library. I'm getting to the limits of my knowledge so want to double check that I'm correctly misunderstanding dynamic linking and that using dladdr() will be OK in all modern Mac, iOS etc. apps.

[Edit: the dladdr() call, above, was fixed with reference to this answer]

Symbolicating iOS crash address returns inappropriate results

When you want to symbolicate use the load address (the second address, it would be better to always use the image base address of the framework/library but this never changed in my experience so far) after the -l flag and then all the symbol addresses of this framework, the architecture and the corresponding iOS version of the framework you want to symbolicate or if it's your application's line then use the dSYM file, e.g. for the UIKit symbols of the iOS 8.1.1

xcrun atos -arch arm64 -o ~/Library/Developer/Xcode/iOS DeviceSupport/8.1.1 (12B436)/Symbols/System/Library/Frameworks/UIKit.framework/UIKit -l <load_address> <symbols_addressess> ...

For your own application lines

xcrun atos -arch arm64 -o MyApp.app.dSYM/Contents/Resources/DWARF/MyApp -l <load_address> <symbols_addressess> ...

And you get all the appropriate results.

Fetch Core Data using UUID

In my case it works with a following predicate:

func getItem(with id: UUID?) -> Item? {
guard let id = id else { return nil }
let request = Item.fetchRequest() as NSFetchRequest<Item>
request.predicate = NSPredicate(format: "%K == %@", "id", id as CVarArg)
guard let items = try? context.fetch(request) else { return nil }
return items.first
}

More importantly, I am using UUID (the same case is in the answer suggested by Martin), not ObjectIdentifier. It is definitely possible to fetch items based on UUID.

Please try to change a parameter type in your function to UUID

How to insert a NEWID() / GUID / UUID into the code editor?

NEWID() itself is a function. when called returns a GUID value.

You do not have to put it in a separate window and then copy paste value from there. Just simply put that function there where you want the GUID value and when the query is executed at run time the value returned by this function will be used.

For instance in an Insert statement

INSERT INTO TableName (Col1 , Col2, Col3)
VALUES (1 , 'Value 1', NEWID())

If you want col3 to have a GUID value you do not need to copy paste the value returned from NEWID() function but you use the function itself. At runtime a guid value will be retuned and inserted into col3.

Similarly if you were updating

UPDATE TableName 
SET Col3 = NEWID()
WHERE <Some Condition>

Again you dont have to copy paste the value returned from NEWID() function just use the function itself.

Another Option would be suppose you are somewhere inside your code where you cannot call the NEWID() function . You would Declare a variable of type UNIQUEIDENTIFIER call the function store its value to that variable and then use that variable inside you code something like ...

DECLARE @GUID_Value UNIQUEIDENTIFIER;
SET @GUID_Value = NEWID();

-- Now use this variable anywhere in your code.

Adding to Keyboard Shortcut

For some strange reason if you want to add a shortcut to your SSMS to generate GUIDs for you. You would need to two thing.

  1. Create a stored Procedure which returns GUID value .
  2. Add a key shortcut to call that stored Procedure.

Proc Definition

CREATE PROCEDURE get_Guid
AS
SELECT NEWID();

Add it to shortcuts

From your SSMS goto Tools --> Options --> Environment --> Keyboard

add the stored procedure's name to the shortcut you want to. Click OK. Close SSMS and reopen it again and you are good to go.

Sample Image

As shown in the above snipshot, now if you press CTRL + 0 it will generate a GUID value for you in the same query window.

Generating a UUID in Postgres for Insert statement?

uuid-ossp is a contrib module, so it isn't loaded into the server by default. You must load it into your database to use it.

For modern PostgreSQL versions (9.1 and newer) that's easy:

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

but for 9.0 and below you must instead run the SQL script to load the extension. See the documentation for contrib modules in 8.4.

For Pg 9.1 and newer instead read the current contrib docs and CREATE EXTENSION. These features do not exist in 9.0 or older versions, like your 8.4.

If you're using a packaged version of PostgreSQL you might need to install a separate package containing the contrib modules and extensions. Search your package manager database for 'postgres' and 'contrib'.



Related Topics



Leave a reply



Submit