|  | // Copyright 2023 The Fuchsia Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include <lib/ld/abi.h> | 
|  | #include <lib/ld/module.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #include "test-start.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | int a; | 
|  |  | 
|  | void test(int n, int o) { | 
|  | int* ap = &a; | 
|  | __asm__("" : "=r"(ap) : "0"(ap)); | 
|  | if (std::exchange(*ap, n) != o) { | 
|  | __builtin_trap(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // TODO(https://fxbug.dev/42083949): clang doesn't support template arguments being used | 
|  | // as part of attribute arguments. | 
|  |  | 
|  | #ifdef __clang__ | 
|  |  | 
|  | [[gnu::constructor(101)]] void ctor0() { test(1, 0); } | 
|  | [[gnu::constructor(102)]] void ctor1() { test(2, 1); } | 
|  |  | 
|  | [[gnu::destructor(102)]] void dtor1() { test(3, 2); } | 
|  | [[gnu::destructor(101)]] void dtor2() { test(4, 3); } | 
|  |  | 
|  | #else | 
|  |  | 
|  | template <int New, int Old> | 
|  | [[gnu::constructor(100 + New)]] void ctor() { | 
|  | test(New, Old); | 
|  | } | 
|  |  | 
|  | template <int New, int Old> | 
|  | [[gnu::destructor(105 - New)]] void dtor() { | 
|  | test(New, Old); | 
|  | } | 
|  |  | 
|  | template void ctor<1, 0>(); | 
|  | template void ctor<2, 1>(); | 
|  |  | 
|  | template void dtor<3, 2>(); | 
|  | template void dtor<4, 3>(); | 
|  |  | 
|  | #endif | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | extern "C" int64_t TestStart() { | 
|  | const auto& executable_module = *ld::abi::_ld_abi.loaded_modules.get(); | 
|  |  | 
|  | if (executable_module.init.size() != 2) { | 
|  | return 1; | 
|  | } | 
|  | executable_module.init.CallInit(executable_module.link_map.addr); | 
|  | if (a != 2) { | 
|  | return 2; | 
|  | } | 
|  |  | 
|  | if (executable_module.fini.size() != 2) { | 
|  | return 3; | 
|  | } | 
|  | executable_module.fini.CallFini(executable_module.link_map.addr); | 
|  | if (a != 4) { | 
|  | return 4; | 
|  | } | 
|  |  | 
|  | return 17; | 
|  | } |