For quite a while I've been using linker sections for registering elements that are used at runtime. I find that it's a simple way to make generic and extensible interface. A particularly useful use-case is something like unit tests or a multitool (e.g. busybox) so one can do something like:
$ ./tool <handler>
Where handler is a simple string that is "looked up" at runtime by walking the linker section. In this way, your parser doesn't have to "know" what commands are supported. It just finds their handlers in the linker section dedicated for them or it doesn't.
With GCC I've been doing something like (you can do this with Clang as well):
#define __tool __attribute__((__section__("tools")))
Then each handler I want to register gets a simple structure (with more or less information as needed)
struct tool {
const char *name;
const char *help;
int (*handler)(int argc, char **argv);
}
Then, for each tool you just do something like (often conveniently wrapped in a macro):
int example_tool0(int argc, char **argv)
{
return -1;
}
static const struct tool example_tool0 = {
.name = "exmaple_tool0",
.help = "usage: ...",
.handler = example_tool0
};
__tool static const struct tool *ptr = &example_tool0;
And used a such:
$ ./tool example_tool0
And because of __tool, each pointer registered in this way is packed into a linker section that can be walked.
Now, on GCC the linker creates two magic variables for each section: __start_SECTION and __stop_SECTION. So, to "walk" all of our registered handlers you just take the size of this section, divide by the size of a pointer, and then strncmp against the name (in this example) in the struct.
All of the above just to say, how can this be done using the OSX/iOS Clang-based toolchain? I would rather not use a custom linker script to achieve this seemingly simple operation.
Is there a way do this on OSX? I have worked around the issue by registering an empty entry at the beginning of the section and at the end. But doing so requires forcing the link order of the object files.
While OSX/iOS uses Clang as their platform compiler, they do not use the LLVM linker. Rather, they implement their own ld64 (which is open source) for whatever reason. So, it may just not be supported. I didn't readily see anything in man ld on OSX, but it's a bit info-dense.
For reference with ELF and GCC
And so this has been answered by others already. I did search, but I must have missed this answer. I've actually looked for an answer to this question many times before but must've never used the right words.
https://stackoverflow.com/a/22366882/2446071
In summary, apparently the linker supports syntax to define these desired symbols yourself:
extern char __start_SECTION __asm("section$start$SEGMENT$SECTION");
extern char __stop_SECTION __asm("section$end$SEGMENT$SECTION");
Related
I have a non-copyable C++ lambda which captures a unique_ptr, and certain situations when compiling with Apple Clang as Objective-C++ cause the lambda to get converted to a block pointer, at which point the compilation fails due to an attempted copy of the lambda. A simple example is as follows:
int main(int argc, const char * argv[])
{
std::unique_ptr<int> myHeapInt = std::make_unique<int>(4);
int myStackInt = 0;
auto myLambda = [&, myHeapInt = std::move(myHeapInt)]()
{
myStackInt = *myHeapInt;
};
if(bool(myLambda)) //Error ar this point
{
*myHeapInt = 5;
}
std::invoke(myLambda);
return 0;
}
The error is as follows:
Call to implicitly-deleted copy constructor of 'const lambda...
Implicit capture of lambda object due to conversion to block pointer here
Is there a way around this conversion?
What is that bool(myLambda)? I have no clue.
The only thing you can do with a lambda is evoke it: myLambda(). You cannot test for whether it exists or anything.
So, I'm not entirely seeing the relevance of Objective-C++ here, as this code doesn't compile as C++ either:
objc++-noncopy-lambda.cpp:15:9: error: cannot convert '(lambda at objc++-noncopy-lambda.cpp:9:21)' to 'bool' without a conversion operator
if (bool(myLambda))
^~~~~~~~~~~~~
1 error generated.
The error message is different; I assume there's some attempt at implicitly converting lambdas to blocks in Objective-C++, I've tried to stay away from weird edge cases like that, but it seems that in the absence of an operator bool it might try the conversion to a block first.
Either way the code you're attempting to write doesn't make any sense and the compiler is correctly rejecting it.
I see in the comments that you're actually trying to do something different. Could you perhaps post a reduced version of the code you're actually trying to write, which supposedly compiles as C++ but not as Objective-C++?
I was trying to compile a templated header-file class replacement for std::function (github.com/Naios/function2) as Objective-C++, which implements a vtable and optimises it if the callable implements operator bool() or can be converted to bool.
In the end I just decided to disable this optimisation if compiled as Objective-C++ as converting to a block pointer is by design in Clang for block-lambda interoperability (http://clang.llvm.org/docs/LanguageExtensions.html#interoperability-with-c-11-lambdas).
We have some functions made available to us in iOS static library. There is a header (.h) and the compiled (.a) file. Is there any way that the functions in the static library can be called from a command line ( either OS X, Windows or Linux )? I have researched this for couple of days now and I am starting to doubt if this is even possible? We don't deal with Apple/iOS/xcode environment and the vendor only has this static library. Any hints? If it is possible in anyway I am open to reading any and very documentation but at this time I am in doubt if this is even possible? thanks
While checking out what is possible, I ran this
lipo -info libExaNumberCalc.a
I ran the above and it says
Architectures in the fat file: libExaNumberCalc.a are : i386 armv7 x86_64 arm64
Wonder if the above adds any hope?
The first thing that springs to mind is that you could write thin wrapper around your library function and build/run it. Something like
// main.c
#include "your_library_header.h"
int main(int argc, char *argv[])
{
// parse & pass parameters if necessary from command line
your_lib_function();
return 0;
}
Build with something like
clang main.c -o output.file -lyourlibrary
I have three question for you, all related to dyld :)
I have been using this dyld man page as a basis. I have compiled the following code and successfully executed the binary on my jailbroken device.
#include <stdio.h>
#include <mach-o/dyld.h>
int main(int argc, const char* argv[]) {
uint32_t image_count, i;
image_count = _dyld_image_count();
for (i = 0; i < image_count; i++) {
printf("%s\n", _dyld_get_image_name(i));
}
return 0;
}
I thought that these functions let me find all the shared libraries that are loaded in my program's address-space. On my mac, the output is pretty straightforward: It shows the paths to all the libraries that are currently loaded in memory. On my iPhone the output is nearly the same - i also get filepaths - but there are no files at the specified location. (On my mac on the other hand, i can locate the files!)
This is a sample line from the output:
/usr/lib/system/libdyld.dylib
According to ls, iFile and all the other tools i've used, this directory (/usr/lib/system/) is empty. Why? Where are those files?
Another thing i'd like to know is: Is it possible to locate a library in memory? From what offset to what offset the library is mapped into memory? I think i know how to find the beginning but i have no idea how to find the end of the library. To find the beginning, i'd use the address returned by _dyld_get_image_header - Is that correct?
Last question: I wanted to load a dynamic lib system-wide so i assumed i could use DYLD_INSERT_LIBRARIES to do just that. However, every binary i try to execute after inserting my lib crashes and produces a bus error! Did i forget something or is it the dynamic library that causes the crash?
the libraries are located at :
/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armv6 (_armv7)
This is a big file were all the single libraries have been joined into one large one.
See http://iphonedevwiki.net/index.php/MobileSubstrate for hooking on jailbroken device
Yes one can determine the position of a dylib in memory, even on non jailbroken devices.
parse the LC_SEGMENT(_TEXT)-Section Header(_text) of the library then you can get the base address of the library and the size of the TEXT __text segment. Then query for the vmslide. Add this to the base address of the TEXT __text.
A detailed description of the mach-o file format can be found here:
https://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html. Pay special attention to "segment_command"-structure.
What is a good way to load a GLSL shader using C/C++ without using Objective-C or any Apple APIs?
I am currently using the following method, which is from the iPhone 3D Programming book, but it says that it is not recommended for production code:
Simple.vsh
const char* SimpleVertexShader = STRINGIFY
(
// Shader code...
);
RenderingEngine.cpp
#define STRINGIFY(A) #A
#include "Simple.vsh"
// ...
glShaderSource( shaderHandle, 1, &SimpleVertexShader, 0 );
If you want to load your shaders from files in your app bundle, you can get the file paths using the NSBundle object (in Objective-C), or using the CoreFoundation CFBundle object (in pure C).
Either way, you are using Apple-specific APIs. The only thing you're getting by using CFBundle instead of NSBundle is more boilerplate code.
If you don't want to use any Apple APIs, then your options are to embed your shaders as literal strings, or connect to a server on the Internet and download them (using the Unix socket API).
What you really need to do is define an interface by which your RenderingEngine gets the source code for its shaders, and implement that interface using the appropriate platform-specific API on each platform to which your port the RenderingEngine. The interface can be something super simple like this:
RenderingEngineShaderSourceInterface.h
#ifdef __cplusplus
extern "C" {
#endif
// You are responsible for freeing the C string that this function returns.
extern char const *RenderingEngine_shaderSourceForName(char const *name);
#ifdef __cplusplus
}
#endif
Then you create RenderingEngineShaderSource_Windows.cpp, RenderingEngineShaderSource_iOS.m, RenderingEngineShaderSource_Linux.cpp, etc. Each one implements RenderingEngine_shaderSourceForName using the appropriate API for that platform.
I use one of two methods. If it's a short shader, I may just put it code:
const char shader[] =
"uniform vec4 blah;\n" // Note, no semicolon here - it does the right thing
"main ()\n"
"{\n"
...rest of code
"}\n";
Or, if it's longer or going to be re-used in other places, I'll put it into a text file in the resources and read the text file at run time. You can get to it via [NSBundle pathForResource:ofType:].
Consider a C++ raw string literal; no STRINGIFY is needed since the newer features of C++ allow you to do similar things without macro.
I'd retype a good example but here is one.
I followed Claus's post to set up code coverage on Xcode 4.2 with LLVM 3.0. I'm able to see test coverage files, but they're only for my unit test classes, not my actual project classes. I've tried setting Generate Test Coverage Files and Instrument Program Flow to Yes on my main target, but that didn't help, as it failed with the following error:
fopen$UNIX2003 called from function llvm_gcda_start_file
To clarify, I don't think that's even the right approach - I just tried it to see if it would generate code coverage on my project classes.
At this point, I'd be happy to try anything that gets code coverage working on my app. Any suggestions?
You are expecting linker problem, profile_rt library uses fopen$UNIX2003 and fwrite$UNIX2003 functions instead of fopen and fwrite.
All you need is to add the following .c file to your project:
#include <stdio.h>
FILE *fopen$UNIX2003( const char *filename, const char *mode )
{
return fopen(filename, mode);
}
size_t fwrite$UNIX2003( const void *a, size_t b, size_t c, FILE *d )
{
return fwrite(a, b, c, d);
}
This code just remaps the missing functions to standard ones.
Note on $UNIX2003 suffix:
I've found an Apple document saying:
The UNIX™ conformance variants use the $UNIX2003 suffix.
Important: The work for UNIX™ conformance started in Mac OS 10.4, but was not completed until 10.5. Thus, in the 10.4 versions of libSystem.dylib, many of the conforming variant symbols (with the $UNIX2003 suffix) exist. The list is not complete, and the conforming behavior of the variant symbols may not be complete, so they should be avoided.
Because the 64-bit environment has no legacy to maintain, it was created to be UNIX™ conforming from the start, without the use of the $UNIX2003 suffix. So, for example, _fputs$UNIX2003 in 32-bit and _fputs in 64-bit will have the same conforming behavior.
So I expect libprofile_rt to be linked against 10.4 SDK.
I use CoverStory http://code.google.com/p/coverstory/ a GUI for .gcda and .gcno files.
The documentation explains the settings needed to generate these files http://code.google.com/p/coverstory/wiki/UsingCoverstory.