blob: dff3e77dde735cffb33fd92db301102447331fcd [file] [log] [blame]
// 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;
}