Change subroutine names at build time to avoid collisions in Xcode

BACKGROUND

I am creating an iOS application (from which I will just call MyApp from here), which will rely on the calculations performed by several separate static libraries (which I will name Lib1 , Lib2 , Lib3 , ...). Each library is built into its own project, then it is imported into one workspace (therefore, the workspace will contain MyApp , Lib1 , Lib2 , ...). Learn more about how it is configured here . Libraries are used by other products that are not dependent on MyApp , so I want to minimize any changes to the libraries. Libraries are also written in (plain) C , so there are no header files.

Certain function names are used by several libraries (therefore, both Lib1 and Lib2 can have a DoStuff method). Functions with the same name, as a rule, do the same thing, but there are some features of how to do this, which may be different between libraries, so the actual code in DoStuff on Lib1 may differ from the code in DoStuff on Lib2 . It would be very difficult to write one universal DoStuff , which would be exactly the same in every library.

RELEASE

While the application is running, it does not call the correct DoStuff from the correct library. I found out about this because during the debugging session the wrong function was called (which ultimately caused the application to crash due to subtle differences in the DoStuff functions).

WHAT I SEEK FOR

Each library has only one entry point from MyApp , and each entry point is uniquely named. If the DoStuff is called from the Lib1 entry point method (or any other method on Lib1 , for that matter), then I want it to call the DoStuff method on Lib1 . What is the best way to do this?

Is there any way (perhaps through customization somewhere in Xcode) that I can make each library have its own namespace? That would be my preferred way to solve the problem. I think I could survive and rename duplicate functions so that they are all unique (so the DoStuff method on Lib1 could be renamed to Lib1DoStuff or something similar), but there are hundreds of functions that could have duplicated names, and we are going to add There are hundreds of libraries in the project, therefore, to go in and rename all the functions manually and fix all the calls to them, it will take a considerable amount of time, and my boss will not see this as a viable option.


UPDATE

After looking at Josh Caswell's comments and some of the links he provided, it seems like you can automatically rename all the functions when compiling the libraries, and that would be the best way to fix the THE ISSUE error. From what I saw, objcopy , which is mentioned in several links in the comments, is not supported by iOS. In the end, I came across a this entry that talks about creating custom build rules for Xcode purposes and this blog post that talks about custom build settings and build steps.

I have the right to assume that at some point in the build process, I can use scripts to automatically add the name of all the functions in each of my libraries instead of doing it manually, as I described in the last paragraph of the WHAT I'M LOOKING FOR above ? If so, what is the right part of the assembly process to make these changes? And finally, what would the syntax look like to do something like this? The "scripts" used in different parts of the build process, of course, are not like Obj-C. I have never used these β€œscripts” before, so I am completely in the dark about how I will use them and what I need help with.

I tried to be as clear as I could, but if you have any questions about what I ask, let me know.

+6
source share
1 answer

Why does xcode not call the correct library function?

Say I have 3 C libraries, as you mentioned. Say it has the following code.

Library 1 - test1lib.a with code:

 #include <stdio.h> void doStuff() { printf("\nDoing stuff for lib1\n"); } void uniqueEntryPoint1() { printf("\nUnique entry point for lib1\n"); doStuff(); } 

Library 2 - test2lib.a with code:

 #include <stdio.h> void doStuff() { printf("\nDoing stuff for lib2\n"); } void uniqueEntryPoint2() { printf("\nUnique entry point for lib2\n"); doStuff(); } 

Library 3 - test3lib.a with code:

 #include <stdio.h> void doStuff() { printf("\nDoing stuff for lib3\n"); } void uniqueEntryPoint3() { printf("\nUnique entry point for lib3\n"); doStuff(); } 

Here, each library has a unique function and one common doStuff() function

When we add these 3 libraries to xcode and link them. xcode, but does not load all object files. Let's say the objective C code looks like this:

 @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. uniqueEntryPoint1(); } 

Output signal

 Unique entry point for lib1 Doing stuff for lib1 

In this case, xcode will only load the characters that are passed (library objects 1) in this case.

If you read about checkboxes or linker options like -all_load , -force_load and -objC , you will have a better understanding.

If we add the -all_load linker option, this will force the linker to load all library objects, so we get the following error in xcode

 ld: 2 duplicate symbols for architecture arm64 clang: error: linker command failed with exit code 1 (use -v to see invocation) 

The reason for this does not work, because the linker detects that doStuff() redefined several times.

The only way to solve this problem is to change the linker input, i.e. characters present in these 3 libraries. This is already mentioned by Josh in the comments. I will add $ 0.02 to it.

Possible solutions

Solution 1:

The best solution (self-evident) is to change the source code if you have access to the same.

Solution 2:

Use objcopy to rename or prefix a function as indicated in the answer to this How to deal with character conflicts between statically linked libraries?

Now you doubt how to find objcopy.

Option 1: You can use this project https://github.com/RodAtDISA/llvm-objcopy . This will be difficult to compile as it builds with llvm. You will need to follow the instructions at http://llvm.org/docs/GettingStarted.html and http://llvm.org/docs/CMake.html .

If you are rewriting https://github.com/RodAtDISA/llvm-objcopy/blob/master/llvm-objcopy.cpp , you can probably reuse the logic of parsing and rewriting objects, regardless of llvm.

Option 2:

Compile and reuse binutils objcopy from https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=binutils/objcopy.c;h=2636ab4bcb34cf1e1e54db9933018a805b366727;

Solution 3:

You can follow the answer provided by Richard in this link Rewrite characters in static iOS libraries . This is more of a hack, but using a hex editor you can rewrite characters if their length is kept the same. If you have more characters and a large library, you can use https://sourceforge.net/projects/bbe-/ and nm write a script.

All this is a considerable effort, but apparently there is no shortcut.

+2
source

Source: https://habr.com/ru/post/1011920/


All Articles