1353944Sdim//===-- ubsan_flags.cpp ---------------------------------------------------===//
2353944Sdim//
3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353944Sdim// See https://llvm.org/LICENSE.txt for license information.
5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353944Sdim//
7353944Sdim//===----------------------------------------------------------------------===//
8353944Sdim//
9353944Sdim// Runtime flags for UndefinedBehaviorSanitizer.
10353944Sdim//
11353944Sdim//===----------------------------------------------------------------------===//
12353944Sdim
13353944Sdim#include "ubsan_platform.h"
14353944Sdim#if CAN_SANITIZE_UB
15353944Sdim#include "ubsan_flags.h"
16353944Sdim#include "sanitizer_common/sanitizer_common.h"
17353944Sdim#include "sanitizer_common/sanitizer_flags.h"
18353944Sdim#include "sanitizer_common/sanitizer_flag_parser.h"
19353944Sdim
20353944Sdim#include <stdlib.h>
21353944Sdim
22353944Sdimnamespace __ubsan {
23353944Sdim
24353944Sdimconst char *MaybeCallUbsanDefaultOptions() {
25353944Sdim  return (&__ubsan_default_options) ? __ubsan_default_options() : "";
26353944Sdim}
27353944Sdim
28353944Sdimstatic const char *GetFlag(const char *flag) {
29353944Sdim  // We cannot call getenv() from inside a preinit array initializer
30353944Sdim  if (SANITIZER_CAN_USE_PREINIT_ARRAY) {
31353944Sdim    return GetEnv(flag);
32353944Sdim  } else {
33353944Sdim    return getenv(flag);
34353944Sdim  }
35353944Sdim}
36353944Sdim
37353944SdimFlags ubsan_flags;
38353944Sdim
39353944Sdimvoid Flags::SetDefaults() {
40353944Sdim#define UBSAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
41353944Sdim#include "ubsan_flags.inc"
42353944Sdim#undef UBSAN_FLAG
43353944Sdim}
44353944Sdim
45353944Sdimvoid RegisterUbsanFlags(FlagParser *parser, Flags *f) {
46353944Sdim#define UBSAN_FLAG(Type, Name, DefaultValue, Description) \
47353944Sdim  RegisterFlag(parser, #Name, Description, &f->Name);
48353944Sdim#include "ubsan_flags.inc"
49353944Sdim#undef UBSAN_FLAG
50353944Sdim}
51353944Sdim
52353944Sdimvoid InitializeFlags() {
53353944Sdim  SetCommonFlagsDefaults();
54353944Sdim  {
55353944Sdim    CommonFlags cf;
56353944Sdim    cf.CopyFrom(*common_flags());
57353944Sdim    cf.external_symbolizer_path = GetFlag("UBSAN_SYMBOLIZER_PATH");
58353944Sdim    OverrideCommonFlags(cf);
59353944Sdim  }
60353944Sdim
61353944Sdim  Flags *f = flags();
62353944Sdim  f->SetDefaults();
63353944Sdim
64353944Sdim  FlagParser parser;
65353944Sdim  RegisterCommonFlags(&parser);
66353944Sdim  RegisterUbsanFlags(&parser, f);
67353944Sdim
68353944Sdim  // Override from user-specified string.
69353944Sdim  parser.ParseString(MaybeCallUbsanDefaultOptions());
70353944Sdim  // Override from environment variable.
71353944Sdim  parser.ParseStringFromEnv("UBSAN_OPTIONS");
72353944Sdim  InitializeCommonFlags();
73353944Sdim  if (Verbosity()) ReportUnrecognizedFlags();
74353944Sdim
75353944Sdim  if (common_flags()->help) parser.PrintFlagDescriptions();
76353944Sdim}
77353944Sdim
78353944Sdim}  // namespace __ubsan
79353944Sdim
80353944SdimSANITIZER_INTERFACE_WEAK_DEF(const char *, __ubsan_default_options, void) {
81353944Sdim  return "";
82353944Sdim}
83353944Sdim
84353944Sdim#endif  // CAN_SANITIZE_UB
85