iOS large file llseek or lseek64 - ios

I can't find any information how to implement in C module of iOS Xcode project lseek() for large files:
llseek()
or
lseek64()
Compilation with:
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
has no effect.
How is this possible to do?

You need to use fseeko() and ftello() when seeking to specific 64bit offsets in a file. Pass the file offset as a off_t instead of int and it will work on both 32bit and 64bit systems.

Related

Does C# spec permit casting from a ulong to an int? Monotouch gives a NumberOverflow

I tested the following code in several environments
ulong c = 10000000000000000; // Base 10
int w = (int) c; // w should be 1874919424
The results are as follows:
VS2013 .NET 4.5 - w = 1874919424
Xamarin (mono) Android - w = 1874919424
Xamarin (mono) iOS - number overflow
Is this an issue that Xamarin should/will fix? (e.g. the C# spec requires it)
Does iOS / Objective C code support this casting? (why isn't this working?)
How can I work around this, without boxing or decreasing performance?
This method is used extensively in BouncyCastle encryption and I'm porting this to C# and want to make as few changes as necessary.
If compiled identically then the behaviour should be identical on all platforms and that should not be related to unified/classic 32/64bits or nint support.
So make sure your iOS project is not build with the Generate overflow checks enabled.
Look for this in Project Options, Build, Compiler in Xamarin Studio or in the command-line options given to the compiler: /checked.

How do I use the ARM assembler in XCode?

Just for educational purposes, I would like to add a function to an existing iPhone app, written in ARM assembly. I don't need a tutorial on ARM assembly in general, because I already read too many of them. I just don't know how to actually run the code!
What I would like to do is something like:
useless.h:
void useless();
useless.s:
useless:
bx lr
If this also works on the simulator it would be fine... On the simulator, the .s file would not compile, so I should maybe do something like:
useless.s:
#if I_AM_ARM
useless:
bx lr
#endif
useless.c:
#if !I_AM_ARM
void useless()
{
}
#endif
I know the syntax I use is broken, but how do I write it correctly? (Breaking an app on the simulator just because I want to try some inline assembly is no option...)
The second-best option would be to use inline assembly, but I would strongly prefer non-inline assembly.
Thanks!
Edit: I want to learn ARM assembly, so I would like to find a method to compile ARM assembly code, and to EXECUTE ARM assembly code.
I finally found the answer myself. It's actually not that hard. I only solved it for the 32-bit ARM version though.
useless.h:
void useless();
useless.s:
#ifdef __arm__
.syntax unified
.globl _useless
.align 2
.code 16
.thumb_func _useless
_useless:
//.cfi_startproc
bx lr
//.cfi_endproc
// CFI means Call Frame Information
// Optionally. Use for better debug-ability.
#endif
useless.c:
#ifndef __arm__
void useless()
{
}
#endif
Notes:
The CLANG ARM Assembler syntax is a bit different from what you see in example all over the web. Comments start with // and /* multiline comments */ are also supported. It also understands the standard C preprocessor. The function has to be defined as a Thumb function, if you specify an arm function (.code 32) the program will just crash. The line .thumb_func _useless can be ommited and it works still. I have no Idea what it means. If you omit the .code 16 line, the program crashes.
about the #ifdef. For ARMv7, __arm__ is defined. For ARMv8, i.e. the 64bit-variant on the iPhone 5S, __arm__ is not defined, but __arm64__ is defined instead. The above code does not work for the 64bit-ARM-version. Instead, the implementation from useless.c will be used. (I didn't forget ARMv7s, I just don't have a device with that arch in my hands currently, so I cannot test.)
The simulator doesn't use arm. you'll have to write x86_64 assembly if you want it to run on the simulator. (probably).
The best way to learn is to take a look at actual working examples, see my blog post about ARM iOS timing. This example Xcode project shows how to mix ARM ASM and C impls of a function. There is also a very accurate timing module to run your code N times, because accurate timing is the hard part when it comes to optimizing the code.
You can emulate ARM-Ubuntu with QEmu (there are some Windows ports of it, e.g. http://lassauge.free.fr/qemu/ ). If you are on Windows, you may need to emulate x86_64-Ubuntu in the middle. To create an ARM image you can follow the steps from this question: Black screen in QEmu for ARM-Ubuntu (how to get GUI?) (yes, unfortunately, you get no GUI with these steps, just a console to the ARM-Ubuntu machine, and you have to do the steps from Ubuntu). Then you can cross-compile your C++/C/Assembly programs from Windows/Ubuntu host to ARM-Ubuntu target.
clang++.exe -Wall test1.cpp -o test1exe -std=c++14 -Ipath-to-arm-linaro/arm-linux-gnueabihf/include/c++/5.3.1 -Ipath-to-arm-linaro/arm-linux-gnueabihf/include/c++/5.3.1/arm-linux-gnueabihf -ffunction-sections -fdata-sections --sysroot=path-to-arm-linaro/arm-linux-gnueabihf/libc --target=arm-unknown-linux-gnueabihf -Bpath-to-arm-linaro/arm-linux-gnueabihf/bin/
For cross-compilation you would need to download and roll out a toolchain, e.g. gcc-linaro-5.3-2016.02-i686-mingw32_arm-linux-gnueabihf.tar.xz (Windows/MinGW) from https://releases.linaro.org/components/toolchain/binaries/latest-5/arm-linux-gnueabihf/ and replace "path-to-arm-linaro" in the above command with the path to the toolchain.
I just started working with iOS. The first thing I tried to do was add asm code to my project and ran into the same problem. The static data is handled slightly differently in 64-bit mode. I discovered how to do it by looking at the assembler output of the compiler. The same .S file will be compiled as both 32 and 64-bit in Xcode, so prepare it like this:
.globl _myfunction
.align 2
my_constant_data:
.byte 0,1,2,3,4,5,6,7
#ifdef __arm__
.thumb_func _myfunction
.syntax unified
.code 16
//
// call from C as my myfunction()
//
_myfunction:
ldr r0,=my_constant_data
< write your thumb-2 code here >
bx lr
#else // or you can use #ifdef __arm64__
//
// Call from C as myfunction()
//
_myfunction:
adrp x0, my_constant_data#PAGE
add x0,x0, my_constant_data#PAGEOFF
< write your Armv8 code here >
ret
#endif

iswalpha() in iOS doesn't return the same value on iOS that it does on MacOS

I have a problem about iswalpha() on iOS.
I am tuning my app in Xcode 4.5 and I tried to pass the Spanish character ú to iswalpha(). The xcode displays the int value of ú is 250.
When I tried to run the app on a real device, iswalpha() returns 0; but in the simulator (I run Xcode on a MacBook air with 10.8.2) it returns 1.
I guess the reason might be iOS has a different implementation of wide-character than does MacOS. What is the best way to resolve this?
Enhanced details:
UTF-16(unicode)encoding of Spanish character ú is 250 in int value. I think iswalpha()should return 1, as MACOS does, other than in iOS return a 0.
Dam new user could not post image here. so for UTF-16 encoding of ú please refer to :
http://www.fileformat.info/info/unicode/char/fa/index.htm
Well I can answer my own question now, as well as a development log in case I forgot this later:
It seems to be a fault of Apple's implementation of libc in iOS. The implementation of iswalpha() is incomplete considering letters in languages other than English. The specific letters(ú,á,ó,...) in different languages could not be recognized by iswalpha(), because they fall out of the 0x7F ASCII boundry, and for somehow it could not be recognized by iOS's locale processing functions, but obviously in different locale those should still be readable alphabet letters.
Some details about it:
iswalph() in iOS is tracked down to:
__DARWIN_CTYPE_static_inline int
__istype(__darwin_ct_rune_t _c, unsigned long _f)
{
#ifdef USE_ASCII
return !!(__maskrune(_c, _f));
#else /* USE_ASCII */
return (isascii(_c) ? !!(_DefaultRuneLocale.__runetype[_c] & _f)
: !!__maskrune(_c, _f));
#endif /* USE_ASCII */
}
and it is __maskrune(_c, _f)) that in the end returns 0.
It is understandable that Apple missed this point since, nobody will use iswalpha() in Objective-C. However it may still be useful to note this point for some porting projects. It was a widely used function so maybe important to many legacy projects that porting to iOS. Hope Apple could fix it in later release.
My workaround now to this problem is to have a wrapper function of iswalpha(), which handle these Latin letters by my own code. Now the app runs flawlessly in my iPhone!

dyld API on iPhone - strange output

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.

Code coverage with Xcode 4.2 - Missing files

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.

Resources