How can I sections out of __TEXT and into a new segment for a mach-o binary?

旧城冷巷雨未停 提交于 2020-06-11 07:15:28

问题


How can I move sections out of the __TEXT segment and into a new segment for a mach-o binary? The reason I'm asking is that I'm trying to make my iPhone app smaller, and the iOS App Store encrypts the __TEXT segment of it prior to compression so that it doesn't compress at all. If I can move all the non-executable sections out of that segment and into a new read-only segment, then I can trim the size of my app by about 9%.


回答1:


On linker level

As already mentioned in @meisel answer this can be done through: So the value to set would be:

-Wl,-rename_section,__TEXT,__sectionName,__NEW_SEGMENT_NAME,__newSectionName

if segment permisions need to be adjusted

-segprot,__NEW_SEGMENT_NAME,rx,rx

Be careful with rwx for executable code, the app will be immediately killed by iOS XNU kernel if rxw running code is detected. It's still fine for simulator. This blog post covers some usage examples.

On function prototype level

Assuming you're using Objective-C (or C for that matter) you can use __attribute__ section(...).
Syntax:
__attribute__ ((section("segmentName,sectionName,[optional]sectionType,[optional]sectionAttribute,[optional]stubSize")))
From https://opensource.apple.com/source/clang/clang-137/src/lib/MC/MCSectionMachO.cpp allowed sectionTypes:

  { "regular",                  "S_REGULAR" },                    // 0x00
  { 0,                          "S_ZEROFILL" },                   // 0x01
  { "cstring_literals",         "S_CSTRING_LITERALS" },           // 0x02
  { "4byte_literals",           "S_4BYTE_LITERALS" },             // 0x03
  { "8byte_literals",           "S_8BYTE_LITERALS" },             // 0x04
  { "literal_pointers",         "S_LITERAL_POINTERS" },           // 0x05
  { "non_lazy_symbol_pointers", "S_NON_LAZY_SYMBOL_POINTERS" },   // 0x06
  { "lazy_symbol_pointers",     "S_LAZY_SYMBOL_POINTERS" },       // 0x07
  { "symbol_stubs",             "S_SYMBOL_STUBS" },               // 0x08
  { "mod_init_funcs",           "S_MOD_INIT_FUNC_POINTERS" },     // 0x09
  { "mod_term_funcs",           "S_MOD_TERM_FUNC_POINTERS" },     // 0x0A
  { "coalesced",                "S_COALESCED" },                  // 0x0B
  { 0, /*FIXME??*/              "S_GB_ZEROFILL" },                // 0x0C
  { "interposing",              "S_INTERPOSING" },                // 0x0D
  { "16byte_literals",          "S_16BYTE_LITERALS" },            // 0x0E
  { 0, /*FIXME??*/              "S_DTRACE_DOF" },                 // 0x0F
  { 0, /*FIXME??*/              "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10
  { "thread_local_regular",     "S_THREAD_LOCAL_REGULAR" },       // 0x11
  { "thread_local_zerofill",    "S_THREAD_LOCAL_ZEROFILL" },      // 0x12
  { "thread_local_variables",   "S_THREAD_LOCAL_VARIABLES" },     // 0x13
  { "thread_local_variable_pointers",
    "S_THREAD_LOCAL_VARIABLE_POINTERS" },                         // 0x14
  { "thread_local_init_function_pointers",
    "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS"},                     // 0x15

Allowed section attributes:

ENTRY("pure_instructions",   S_ATTR_PURE_INSTRUCTIONS)
ENTRY("no_toc",              S_ATTR_NO_TOC)
ENTRY("strip_static_syms",   S_ATTR_STRIP_STATIC_SYMS)
ENTRY("no_dead_strip",       S_ATTR_NO_DEAD_STRIP)
ENTRY("live_support",        S_ATTR_LIVE_SUPPORT)
ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE)
ENTRY("debug",               S_ATTR_DEBUG)
ENTRY("" /*FIXME*/,          S_ATTR_SOME_INSTRUCTIONS)
ENTRY("" /*FIXME*/,          S_ATTR_EXT_RELOC)
ENTRY("" /*FIXME*/,          S_ATTR_LOC_RELOC)

Some examples:

//Variable in brand new segment & section, segment VM access defaults to read/write
int intInCustomPlace __attribute__ ( (section ("__DATA2,__data2") ));

//Read only string constant outside of __TEXT in readonly __LINKEDIT
char *kString __attribute__ ( (section ("__LINKEDIT,__customSection") )) = "value";

//C function in custom segment & section
void foo() __attribute__ ( (section ("__TEXT_EXEC,__customSection") ));

//obj-c method in custom section
- (void) foo:(NSInteger)someArg  __attribute__ ( (section ("__TEXT, __customSection") ));

Bear in mind you can easily break stuff, MachOView is a convenient tool for inspecting your binary. Custom ("__TEXT,__cstring") replacement would be most likely your best shot.

EDIT: A nonexisting segment by default will be emitted as readable & writeable (just like __DATA) so this won't work for executable code.

If you want explore the inline assembly path it's documented here: https://developer.apple.com/library/content/documentation/DeveloperTools/Reference/Assembler/040-Assembler_Directives/asm_directives.html




回答2:


ld's -rename_section flag does the job.



来源:https://stackoverflow.com/questions/47896174/how-can-i-sections-out-of-text-and-into-a-new-segment-for-a-mach-o-binary

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!