├── .gitignore ├── jni ├── Application.mk ├── Android.mk └── krait_signal_handler.c ├── README.md ├── .yamato └── build.yml └── PrepareAndroidSDK.pm /.gitignore: -------------------------------------------------------------------------------- 1 | builds.zip 2 | obj -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_ABI := armeabi-v7a 2 | APP_PLATFORM := android-16 3 | NDK_TOOLCHAIN_VERSION := clang 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # krait-signal-handler 2 | A signal handler wrapper in THUMB mode, to work-around the undefined behavior of the IF-THEN/SKIP state when in ARM mode. 3 | 4 | See https://lore.kernel.org/patchwork/patch/416040/ 5 | -------------------------------------------------------------------------------- /.yamato/build.yml: -------------------------------------------------------------------------------- 1 | name: Build Krait Signal Handler 2 | 3 | agent: 4 | type: Unity::VM::osx 5 | image: build-system/unity-extra-macos-10.13-katana:v0.3.6-621005 6 | flavor: b1.xlarge 7 | 8 | commands: 9 | - perl build.pl 10 | 11 | artifacts: 12 | artifacts: 13 | paths: 14 | - builds.zip 15 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := krait-signal-handler 6 | LOCAL_SRC_FILES := krait_signal_handler.c 7 | LOCAL_CFLAGS := -Wall -Werror 8 | 9 | ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) 10 | LOCAL_CFLAGS += -mthumb 11 | endif 12 | 13 | include $(BUILD_STATIC_LIBRARY) 14 | -------------------------------------------------------------------------------- /jni/krait_signal_handler.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SIGMAX 64 5 | 6 | static void (*wrapped_signal_handlers[SIGMAX]) (int, siginfo_t *, void *); 7 | 8 | static void signal_handler(int signum, siginfo_t* siginfo, void* sigcontext) 9 | { 10 | if (wrapped_signal_handlers[signum]) 11 | wrapped_signal_handlers[signum](signum, siginfo, sigcontext); 12 | } 13 | 14 | extern int __real_sigaction(int signum, const struct sigaction *action, struct sigaction *old_action); 15 | int __wrap_sigaction(int signum, const struct sigaction *action, struct sigaction *old_action) 16 | { 17 | struct sigaction wrapper_action_data; 18 | struct sigaction* wrapper_action = NULL; 19 | 20 | if (signum >= SIGMAX) 21 | return __real_sigaction(signum, action, old_action); 22 | 23 | // patch sig action with our thumb compiled dispatcher 24 | if (action) 25 | { 26 | wrapper_action = &wrapper_action_data; 27 | memcpy(wrapper_action, action, sizeof(*action)); 28 | wrapper_action->sa_sigaction = signal_handler; 29 | } 30 | 31 | // install handler (abort on error) 32 | if (__real_sigaction(signum, wrapper_action, old_action) == -1) 33 | return -1; 34 | 35 | // hide any previously installed wrapper 36 | if (old_action && old_action->sa_sigaction == signal_handler) 37 | old_action->sa_sigaction = wrapped_signal_handlers[signum]; 38 | 39 | // add action to dispatch table 40 | if (action) 41 | wrapped_signal_handlers[signum] = action->sa_sigaction; 42 | 43 | return 0; 44 | } 45 | 46 | #undef SIGMAX 47 | -------------------------------------------------------------------------------- /PrepareAndroidSDK.pm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | package PrepareAndroidSDK; 4 | 5 | use strict; 6 | use warnings; 7 | use Carp qw(croak carp); 8 | use File::Path qw(mkpath rmtree); 9 | use File::Spec::Functions; 10 | use File::Copy; 11 | use File::Basename; 12 | 13 | require Exporter; 14 | our @ISA = qw(Exporter); 15 | our @EXPORT_OK=qw(GetAndroidSDK); 16 | 17 | our $SDK_ROOT_ENV = "ANDROID_SDK_ROOT"; 18 | our $NDK_ROOT_ENV = "ANDROID_NDK_ROOT"; 19 | 20 | # based on https://dl-ssl.google.com/android/repository/repository-7.xml 21 | 22 | our $BASE_URL_SDK = "http://dl.google.com/android/repository/"; 23 | our $BASE_URL_NDK = "http://dl.google.com/android/ndk/"; 24 | 25 | our $sdks = 26 | { 27 | "android-7" => "android-2.1_r03-linux.zip", 28 | "android-8" => "android-2.2_r03-linux.zip", 29 | "android-9" => "android-2.3.1_r02-linux.zip", 30 | "android-10" => "android-2.3.3_r02-linux.zip", 31 | "android-11" => "android-3.0_r02-linux.zip", 32 | "android-12" => "android-3.1_r03-linux.zip", 33 | "android-13" => "android-3.2_r01-linux.zip", 34 | "android-14" => "android-14_r03.zip", 35 | "android-15" => "android-15_r03.zip", 36 | "android-16" => "android-16_r02.zip", 37 | "android-17" => "android-17_r01.zip", 38 | }; 39 | 40 | our $sdk_tools = 41 | { 42 | "version" => "20", 43 | "windows" => "tools_r20-windows.zip", 44 | "linux" => "tools_r20-linux.zip", 45 | "macosx" => "tools_r20-macosx.zip", 46 | }; 47 | 48 | our $platform_tools = 49 | { 50 | "version" => "14", 51 | "windows" => "platform-tools_r12-windows.zip", 52 | "linux" => "platform-tools_r12-linux.zip", 53 | "macosx" => "platform-tools_r12-macosx.zip", 54 | }; 55 | 56 | our $ndks = 57 | { 58 | "r5" => 59 | { 60 | "windows" => "android-ndk-r5-windows.zip", 61 | "macosx" => "android-ndk-r5-darwin-x86.tar.bz2", 62 | "linux" => "android-ndk-r5-linux-x86.tar.bz2", 63 | }, 64 | "r5b" => 65 | { 66 | "windows" => "android-ndk-r5b-windows.zip", 67 | "macosx" => "android-ndk-r5b-darwin-x86.tar.bz2", 68 | "linux" => "android-ndk-r5b-linux-x86.tar.bz2", 69 | }, 70 | "r5c" => 71 | { 72 | "windows" => "android-ndk-r5c-windows.zip", 73 | "macosx" => "android-ndk-r5c-darwin-x86.tar.bz2", 74 | "linux" => "android-ndk-r5c-linux-x86.tar.bz2", 75 | }, 76 | "r6" => 77 | { 78 | "windows" => "android-ndk-r6-windows.zip", 79 | "macosx" => "android-ndk-r6-darwin-x86.tar.bz2", 80 | "linux" => "android-ndk-r6-linux-x86.tar.bz2", 81 | }, 82 | "r6b" => 83 | { 84 | "windows" => "android-ndk-r6b-windows.zip", 85 | "macosx" => "android-ndk-r6b-darwin-x86.tar.bz2", 86 | "linux" => "android-ndk-r6b-linux-x86.tar.bz2", 87 | }, 88 | "r7" => 89 | { 90 | "windows" => "android-ndk-r7-windows.zip", 91 | "macosx" => "android-ndk-r7-darwin-x86.tar.bz2", 92 | "linux" => "android-ndk-r7-linux-x86.tar.bz2", 93 | }, 94 | "r7b" => 95 | { 96 | "windows" => "android-ndk-r7b-windows.zip", 97 | "macosx" => "android-ndk-r7b-darwin-x86.tar.bz2", 98 | "linux" => "android-ndk-r7b-linux-x86.tar.bz2", 99 | }, 100 | "r7c" => 101 | { 102 | "windows" => "android-ndk-r7c-windows.zip", 103 | "macosx" => "android-ndk-r7c-darwin-x86.tar.bz2", 104 | "linux" => "android-ndk-r7c-linux-x86.tar.bz2", 105 | }, 106 | "r8" => 107 | { 108 | "windows" => "android-ndk-r8-windows.zip", 109 | "macosx" => "android-ndk-r8-darwin-x86.tar.bz2", 110 | "linux" => "android-ndk-r8-linux-x86.tar.bz2", 111 | }, 112 | "r8b" => 113 | { 114 | "windows" => "android-ndk-r8b-windows.zip", 115 | "macosx" => "android-ndk-r8b-darwin-x86.tar.bz2", 116 | "linux" => "android-ndk-r8b-linux-x86.tar.bz2", 117 | }, 118 | "r8c" => 119 | { 120 | "windows" => "android-ndk-r8c-windows.zip", 121 | "macosx" => "android-ndk-r8c-darwin-x86.tar.bz2", 122 | "linux" => "android-ndk-r8c-linux-x86.tar.bz2", 123 | }, 124 | "r8e" => 125 | { 126 | "windows" => "android-ndk-r8e-windows.zip", 127 | "macosx" => "android-ndk-r8e-darwin-x86.tar.bz2", 128 | "linux" => "android-ndk-r8e-linux-x86.tar.bz2", 129 | }, 130 | "r9" => 131 | { 132 | "windows" => "android-ndk-r9-windows.zip", 133 | "macosx" => "android-ndk-r9-darwin-x86.tar.bz2", 134 | "linux" => "android-ndk-r9-linux-x86.tar.bz2", 135 | }, 136 | "r13b" => 137 | { 138 | "windows" => "android-ndk-13b-windows-x86_64.zip", 139 | "macosx" => "android-ndk-r13b-darwin-x86_64.zip", 140 | "linux" => "android-ndk-r13b-linux-x86_64.zip", 141 | }, 142 | "r16b" => 143 | { 144 | "windows" => "android-ndk-16b-windows-x86_64.zip", 145 | "macosx" => "android-ndk-r16b-darwin-x86_64.zip", 146 | "linux" => "android-ndk-r16b-linux-x86_64.zip", 147 | }, 148 | }; 149 | 150 | our $ndk_base_urls = 151 | { 152 | "r5" => $BASE_URL_NDK, 153 | "r5b" => $BASE_URL_NDK, 154 | "r5c" => $BASE_URL_NDK, 155 | "r6" => $BASE_URL_NDK, 156 | "r6b" => $BASE_URL_NDK, 157 | "r7" => $BASE_URL_NDK, 158 | "r7b" => $BASE_URL_NDK, 159 | "r7c" => $BASE_URL_NDK, 160 | "r8" => $BASE_URL_NDK, 161 | "r8b" => $BASE_URL_NDK, 162 | "r8c" => $BASE_URL_NDK, 163 | "r8e" => $BASE_URL_NDK, 164 | "r9" => $BASE_URL_NDK, 165 | "r13b" => $BASE_URL_SDK, 166 | "r16b" => $BASE_URL_SDK, 167 | }; 168 | 169 | our ($HOST_ENV, $TMP, $HOME, $WINZIP); 170 | 171 | sub GetAndroidSDK 172 | { 173 | if(lc $^O eq 'darwin') 174 | { 175 | $HOST_ENV = "macosx"; 176 | $TMP = $ENV{"TMPDIR"}; 177 | $HOME = $ENV{"HOME"}; 178 | } 179 | elsif(lc $^O eq 'linux') 180 | { 181 | $HOST_ENV = "linux"; 182 | $TMP = "/tmp"; 183 | $HOME = $ENV{"HOME"}; 184 | } 185 | elsif(lc $^O eq 'mswin32') 186 | { 187 | $HOST_ENV = "windows"; 188 | $TMP = $ENV{"TMP"}; 189 | $HOME = $ENV{"USERPROFILE"}; 190 | if (-e "Tools/WinUtils/7z/7z.exe") 191 | { 192 | $WINZIP = "Tools/WinUtils/7z/7z.exe"; 193 | } 194 | } 195 | elsif(lc $^O eq 'cygwin') 196 | { 197 | $HOST_ENV = "windows"; 198 | $TMP = $ENV{"TMP"}; 199 | $HOME = $ENV{"HOME"}; 200 | } 201 | else 202 | { 203 | die "UNKNOWN " . $^O; 204 | } 205 | 206 | print "Environment:\n"; 207 | print "\tHost = $HOST_ENV\n"; 208 | print "\tTemporary = $TMP\n"; 209 | print "\tHome = $HOME\n"; 210 | print "\n"; 211 | print "\t\$$SDK_ROOT_ENV = $ENV{$SDK_ROOT_ENV}\n" if ($ENV{$SDK_ROOT_ENV}); 212 | print "\t\$$NDK_ROOT_ENV = $ENV{$NDK_ROOT_ENV}\n" if ($ENV{$NDK_ROOT_ENV}); 213 | print "\n"; 214 | 215 | my ($sdk, $tools, $ndk, $setenv) = @_; 216 | 217 | if ($sdk or $tools) 218 | { 219 | if ($sdk) 220 | { 221 | print "Installing SDK '$sdk':\n"; 222 | } 223 | elsif($tools) 224 | { 225 | print "Installing SDK Tools '$tools':\n"; 226 | } 227 | 228 | if (!$ENV{$SDK_ROOT_ENV}) 229 | { 230 | $ENV{$SDK_ROOT_ENV} = catfile($HOME, "android-sdk_auto"); 231 | print "\t\$$SDK_ROOT_ENV not set; using $ENV{$SDK_ROOT_ENV} instead\n"; 232 | } 233 | 234 | if (not $tools and $sdk) 235 | { 236 | my @split = split('-', $sdk); 237 | $tools = $split[1]; 238 | } 239 | if ($tools) 240 | { 241 | PrepareSDKTools($tools); 242 | } 243 | if ($sdk) 244 | { 245 | PrepareSDK($sdk); 246 | } 247 | print "\n"; 248 | } 249 | 250 | if ($ndk) 251 | { 252 | print "Installing NDK '$ndk':\n"; 253 | if (!$ENV{$NDK_ROOT_ENV}) 254 | { 255 | $ENV{$NDK_ROOT_ENV} = catfile($HOME, "android-ndk_auto-" . $ndk); 256 | print "\t\$$NDK_ROOT_ENV not set; using $ENV{$NDK_ROOT_ENV} instead\n"; 257 | } 258 | PrepareNDK($ndk); 259 | print "\n"; 260 | } 261 | 262 | my $export = "export"; 263 | if (lc $^O eq 'mswin32') 264 | { 265 | $export = "set"; 266 | } 267 | 268 | if ($setenv and ($ENV{$SDK_ROOT_ENV} or $ENV{$SDK_ROOT_ENV})) 269 | { 270 | print "Outputing updated environment:\n"; 271 | print "\t'$setenv'\n"; 272 | open (SETENV, '>' . $setenv); 273 | print SETENV "$export $SDK_ROOT_ENV=$ENV{$SDK_ROOT_ENV}\n" if ($ENV{$SDK_ROOT_ENV}); 274 | print SETENV "$export $NDK_ROOT_ENV=$ENV{$NDK_ROOT_ENV}\n" if ($ENV{$NDK_ROOT_ENV}); 275 | close (SETENV); 276 | print "\n"; 277 | } 278 | 279 | print "Environment:\n" if ($ENV{$SDK_ROOT_ENV} or $ENV{$SDK_ROOT_ENV}); 280 | print "\t\$$SDK_ROOT_ENV = $ENV{$SDK_ROOT_ENV}\n" if ($ENV{$SDK_ROOT_ENV}); 281 | print "\t\$$NDK_ROOT_ENV = $ENV{$NDK_ROOT_ENV}\n" if ($ENV{$NDK_ROOT_ENV}); 282 | print "\n"; 283 | } 284 | 285 | sub PrepareSDKTools 286 | { 287 | my ($sdk_version) = @_; 288 | my $current_version = 0; 289 | 290 | print "\tMinimum SDK Tools = $sdk_version\n"; 291 | my $sdk_root = $ENV{$SDK_ROOT_ENV}; 292 | my $sdk_tool_path = catfile($sdk_root, "tools"); 293 | my $platform_tool_path = catfile($sdk_root, "platform-tools"); 294 | if (open PROPS, "<", catfile("$sdk_tool_path", "source.properties")) 295 | { 296 | my @content = ; 297 | close PROPS; 298 | chomp(@content); 299 | foreach (@content) 300 | { 301 | if (index($_, "Pkg.Revision") != -1) 302 | { 303 | my @tokens = split('=', $_); 304 | $current_version = int($tokens[1]); 305 | } 306 | } 307 | print "\tInstalled SDK Tools = $current_version\n"; 308 | } 309 | if ($current_version >= $sdk_version and -e catfile($platform_tool_path, "NOTICE.txt") ) 310 | { 311 | print "\tSDK tools are already installed.\n"; 312 | return; 313 | } 314 | if ($sdk_version > $sdk_tools->{'version'}) 315 | { 316 | die "Unknown SDK Tools = $sdk_version\n"; 317 | } 318 | my $sdk_tool = $sdk_tools->{$HOST_ENV}; 319 | my $platform_tool = $platform_tools->{$HOST_ENV}; 320 | die ("Unknown host environment '$HOST_ENV'") if (!$sdk_tool or !$platform_tool); 321 | 322 | print "\tDownloading '$sdk_tool' to '$sdk_tool_path'\n"; 323 | DownloadAndUnpackArchive($BASE_URL_SDK . $sdk_tool, $sdk_tool_path); 324 | 325 | print "\tDownloading '$platform_tool' to '$platform_tool_path'\n"; 326 | DownloadAndUnpackArchive($BASE_URL_SDK . $platform_tool, $platform_tool_path); 327 | } 328 | 329 | sub PrepareSDK 330 | { 331 | my $sdk_root = $ENV{$SDK_ROOT_ENV}; 332 | 333 | my ($sdk) = @_; 334 | 335 | if (IsPlatformInstalled($sdk)) 336 | { 337 | print "\tPlatform '$sdk' is already installed\n"; 338 | return; 339 | } 340 | 341 | my $platform = $sdks->{$sdk}; 342 | die ("Unknown platform API '$sdk'") if (!$platform); 343 | 344 | my $output = catfile($sdk_root, "platforms", $sdk); 345 | print "\tDownloading '$platform' to '$output'\n"; 346 | DownloadAndUnpackArchive($BASE_URL_SDK . $platform, $output); 347 | } 348 | 349 | sub IsPlatformInstalled 350 | { 351 | my $sdk_root = $ENV{$SDK_ROOT_ENV}; 352 | my ($sdk) = @_; 353 | if (! $sdk_root) 354 | { 355 | return 0; 356 | } 357 | unless (grep {$_ eq $sdk} GetCurrentSDKPlatforms($sdk_root)) 358 | { 359 | return 0; 360 | } 361 | return 1; 362 | } 363 | 364 | sub GetCurrentSDKPlatforms 365 | { 366 | my ($sdk_root) = @_; 367 | my $platform_root = $sdk_root . "/platforms"; 368 | opendir(my $dh, $platform_root) || return; 369 | my @platforms = grep { !/^\.\.?$/ && -e catfile($platform_root, $_, "android.jar") } readdir($dh); 370 | closedir $dh; 371 | 372 | return @platforms; 373 | } 374 | 375 | sub DownloadAndUnpackArchive 376 | { 377 | my ($url, $output) = @_; 378 | my ($base,$base_url,$suffix) = fileparse($url, qr/\.[^.]*/); 379 | my ($dest_name,$dest_path) = fileparse($output); 380 | 381 | my $temporary_download_path = catfile($TMP, $base . $suffix); 382 | my $temporary_unpack_path = catfile($TMP, $base . "_unpack"); 383 | 384 | print "\t\tURL: " . $url . "\n"; 385 | print "\t\tOutput: " . $output . "\n"; 386 | print "\t\tBase: " . $base . "\n"; 387 | print "\t\tURL base: " . $base_url . "\n"; 388 | print "\t\tSuffix: " . $suffix . "\n"; 389 | print "\t\tTmp DL: " . $temporary_download_path . "\n"; 390 | print "\t\tTmp unpack: " . $temporary_unpack_path . "\n"; 391 | print "\t\tDest path: " . $dest_path . "\n"; 392 | print "\t\tDest name: " . $dest_name . "\n"; 393 | 394 | # remove old output 395 | rmtree($output); 396 | mkpath($dest_path); 397 | 398 | # create temporary locations 399 | unlink($temporary_download_path); 400 | rmtree($temporary_unpack_path); 401 | mkpath($temporary_unpack_path); 402 | 403 | system("lwp-download", $url, $temporary_download_path); 404 | 405 | if ($WINZIP) 406 | { 407 | system($WINZIP, "x", $temporary_download_path, "-o" . $temporary_unpack_path); 408 | } 409 | else 410 | { 411 | if (lc $suffix eq '.zip') 412 | { 413 | system("unzip", "-q", $temporary_download_path, "-d", $temporary_unpack_path); 414 | } 415 | elsif (lc $suffix eq '.bz2') 416 | { 417 | system("tar", "-xf", $temporary_download_path, "-C", $temporary_unpack_path); 418 | } 419 | else 420 | { 421 | die "Unknown file extension '" . $suffix . "'\n"; 422 | } 423 | } 424 | 425 | opendir(my $dh, $temporary_unpack_path); 426 | my @dirs = grep { !/^\.\.?$/ && -d catfile($temporary_unpack_path, $_) } readdir($dh); 427 | closedir $dh; 428 | my $unpacked_subdir = catfile($temporary_unpack_path, $dirs[0]); 429 | 430 | move($unpacked_subdir, $output) or system("mv $unpacked_subdir $output"); 431 | 432 | # clean up 433 | unlink($temporary_download_path); 434 | rmtree($temporary_unpack_path); 435 | } 436 | 437 | 438 | sub PrepareNDK 439 | { 440 | my ($ndk) = @_; 441 | my $ndk_root = $ENV{$NDK_ROOT_ENV}; 442 | $ndk_root = $1 if($ndk_root=~/(.*)\/$/); 443 | 444 | if (-e $ndk_root and open RELEASE, "<", catfile("$ndk_root", "RELEASE.TXT")) 445 | { 446 | my @content = ; 447 | close RELEASE; 448 | chomp(@content); 449 | my $current = $content[0]; 450 | print "\tCurrently installed = " . $current . "\n"; 451 | 452 | # remove the possible '(64-bit)' from the end 453 | my @curr_arr = split(' ', $current); 454 | $current = $curr_arr[0]; 455 | 456 | if ($ndk eq $current) 457 | { 458 | print "\tNDK '$ndk' is already installed\n"; 459 | return; 460 | } 461 | else 462 | { 463 | my ($current_name,$path) = fileparse($ndk_root); 464 | 465 | $ENV{$NDK_ROOT_ENV} = catfile($path, "android-ndk-" . $ndk); 466 | print "\t\$$NDK_ROOT_ENV is pointing to a mismatching NDK; using $ENV{$NDK_ROOT_ENV} instead\n"; 467 | PrepareNDK($ndk); 468 | return; 469 | } 470 | } 471 | 472 | rmtree($ndk_root); 473 | 474 | my $archive = $ndks->{$ndk}->{$HOST_ENV}; 475 | die ("Unknown NDK release '$ndk' (for $HOST_ENV)") if (!$archive); 476 | 477 | print "\tDownloading '$ndk' to '$ndk_root'\n"; 478 | DownloadAndUnpackArchive($ndk_base_urls->{$ndk} . $archive, $ndk_root); 479 | } 480 | 481 | 1; 482 | --------------------------------------------------------------------------------