163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris/*
263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * Copyright (C) 2015 The Android Open Source Project
363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * All rights reserved.
463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris *
563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * Redistribution and use in source and binary forms, with or without
663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * modification, are permitted provided that the following conditions
763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * are met:
863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris *  * Redistributions of source code must retain the above copyright
963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris *    notice, this list of conditions and the following disclaimer.
1063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris *  * Redistributions in binary form must reproduce the above copyright
1163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris *    notice, this list of conditions and the following disclaimer in
1263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris *    the documentation and/or other materials provided with the
1363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris *    distribution.
1463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris *
1563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
1863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
1963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris * SUCH DAMAGE.
2763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris */
2863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
2963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <ctype.h>
3063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <errno.h>
3163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <limits.h>
3263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <signal.h>
3363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <stdlib.h>
3463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <string.h>
3563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <sys/cdefs.h>
3663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
3763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <string>
3863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <vector>
3963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
4063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <sys/system_properties.h>
4163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
4263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include <private/bionic_macros.h>
4363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
4463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include "Config.h"
4563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris#include "debug_log.h"
4663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
47598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris// Config constants
48598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr uint8_t DEFAULT_FILL_ALLOC_VALUE = 0xeb;
49598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr uint8_t DEFAULT_FILL_FREE_VALUE = 0xef;
50598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris
51598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr uint8_t DEFAULT_FRONT_GUARD_VALUE = 0xaa;
52598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr uint8_t DEFAULT_REAR_GUARD_VALUE = 0xbb;
53598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris
54598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris// Used as the default for all guard values.
55598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr size_t DEFAULT_GUARD_BYTES = 32;
56598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr size_t MAX_GUARD_BYTES = 16384;
57598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris
58598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr size_t DEFAULT_BACKTRACE_FRAMES = 16;
59598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr size_t MAX_BACKTRACE_FRAMES = 256;
60598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris
61598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr size_t DEFAULT_EXPAND_BYTES = 16;
62598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr size_t MAX_EXPAND_BYTES = 16384;
63598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris
64598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr size_t DEFAULT_FREE_TRACK_ALLOCATIONS = 100;
65598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferrisstatic constexpr size_t MAX_FREE_TRACK_ALLOCATIONS = 16384;
66598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris
6763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisstruct Feature {
68166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris  Feature(std::string name, size_t default_value, size_t min_value, size_t max_value,
69166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris          uint64_t option, size_t* value, bool* config, bool combo_option)
70166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris      : name(name), default_value(default_value), min_value(min_value), max_value(max_value),
71166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris        option(option), value(value), config(config), combo_option(combo_option) {}
7263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  std::string name;
7363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  size_t default_value = 0;
74166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris  size_t min_value = 0;
75166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris  size_t max_value = 0;
7663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
7763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  uint64_t option = 0;
7863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  size_t* value = nullptr;
7963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  bool* config = nullptr;
8063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  // If set to true, then all of the options following are set on until
8163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  // for which the combo_option value is set.
8263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  bool combo_option = false;
8363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris};
8463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
8563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisclass PropertyParser {
8663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris public:
8763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  PropertyParser(const char* property) : cur_(property) {}
8863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
8963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  bool Get(std::string* property, size_t* value, bool* value_set);
9063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
9163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  bool Done() { return done_; }
9263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
9363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  void LogUsage();
9463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
9563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris private:
9663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  const char* cur_ = nullptr;
9763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
9863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  bool done_ = false;
9963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
10063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  DISALLOW_COPY_AND_ASSIGN(PropertyParser);
10163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris};
10263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
10363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisbool PropertyParser::Get(std::string* property, size_t* value, bool* value_set) {
10463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  // Process each property name we can find.
10563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  while (isspace(*cur_))
10663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    ++cur_;
10763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
10863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  if (*cur_ == '\0') {
10963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    done_ = true;
11063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    return false;
11163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  }
11263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
11363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  const char* property_start = cur_;
11463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  while (!isspace(*cur_) && *cur_ != '=' && *cur_ != '\0')
11563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    ++cur_;
11663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
11763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  *property = std::string(property_start, cur_ - property_start);
11863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
11963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  // Skip any spaces after the name.
12063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  while (isspace(*cur_) && *cur_ != '=' && *cur_ != '\0')
12163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    ++cur_;
12263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
12363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  if (*cur_ == '=') {
12463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    ++cur_;
12563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    errno = 0;
12663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    *value_set = true;
12763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    char* end;
12863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    long read_value = strtol(cur_, const_cast<char**>(&end), 10);
12963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    if (errno != 0) {
13063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      error_log("%s: bad value for option '%s': %s", getprogname(), property->c_str(),
13163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris                strerror(errno));
13263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      return false;
13363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    }
13463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    if (cur_ == end || (!isspace(*end) && *end != '\0')) {
13563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      if (cur_ == end) {
13663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris        error_log("%s: bad value for option '%s'", getprogname(), property->c_str());
13763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      } else {
13863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris        error_log("%s: bad value for option '%s', non space found after option: %s",
13963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris                  getprogname(), property->c_str(), end);
14063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      }
14163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      return false;
142166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris    } else if (read_value < 0) {
143166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris      error_log("%s: bad value for option '%s', value cannot be negative: %ld",
14463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris                getprogname(), property->c_str(), read_value);
14563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      return false;
14663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    }
14763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    *value = static_cast<size_t>(read_value);
14863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    cur_ = end;
14963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  } else {
15063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    *value_set = false;
15163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  }
15263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  return true;
15363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris}
15463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
15563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisvoid PropertyParser::LogUsage() {
15663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("malloc debug options usage:");
15763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
15863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  front_guard[=XX]");
15963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    Enables a front guard on all allocations. If XX is set");
16063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    it sets the number of bytes in the guard. The default is");
161598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  error_log("    %zu bytes, the max bytes is %zu.", DEFAULT_GUARD_BYTES, MAX_GUARD_BYTES);
16263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
16363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  rear_guard[=XX]");
16463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    Enables a rear guard on all allocations. If XX is set");
16563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    it sets the number of bytes in the guard. The default is");
166598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  error_log("    %zu bytes, the max bytes is %zu.", DEFAULT_GUARD_BYTES, MAX_GUARD_BYTES);
16763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
16863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  guard[=XX]");
16963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    Enables both a front guard and a rear guard on all allocations.");
17063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    If XX is set it sets the number of bytes in both guards.");
171598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  error_log("    The default is %zu bytes, the max bytes is %zu.",
172598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            DEFAULT_GUARD_BYTES, MAX_GUARD_BYTES);
17363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
17463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  backtrace[=XX]");
17563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    Enable capturing the backtrace at the point of allocation.");
17663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    If XX is set it sets the number of backtrace frames.");
177598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  error_log("    The default is %zu frames, the max number of frames is %zu.",
178598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
17963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
18063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  backtrace_enable_on_signal[=XX]");
18163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    Enable capturing the backtrace at the point of allocation.");
18263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    The backtrace capture is not enabled until the process");
18363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    receives a signal. If XX is set it sets the number of backtrace");
184598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  error_log("    frames. The default is %zu frames, the max number of frames is %zu.",
185598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
18663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
18763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  fill_on_alloc[=XX]");
18863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    On first allocation, fill with the value 0x%02x.", DEFAULT_FILL_ALLOC_VALUE);
18963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    If XX is set it will only fill up to XX bytes of the");
19063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    allocation. The default is to fill the entire allocation.");
19163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
19263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  fill_on_free[=XX]");
19363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    On free, fill with the value 0x%02x. If XX is set it will",
19463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris            DEFAULT_FILL_FREE_VALUE);
19563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    only fill up to XX bytes of the allocation. The default is to");
19663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    fill the entire allocation.");
19763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
19863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  fill[=XX]");
19963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    On both first allocation free, fill with the value 0x%02x on",
20063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris            DEFAULT_FILL_ALLOC_VALUE);
20163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    first allocation and the value 0x%02x. If XX is set, only fill",
20263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris            DEFAULT_FILL_FREE_VALUE);
20363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    up to XX bytes. The default is to fill the entire allocation.");
20463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
20563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  expand_alloc[=XX]");
20663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    Allocate an extra number of bytes for every allocation call.");
20763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    If XX is set, that is the number of bytes to expand the");
208598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  error_log("    allocation by. The default is %zu bytes, the max bytes is %zu.",
209598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            DEFAULT_EXPAND_BYTES, MAX_EXPAND_BYTES);
21063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
21163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  free_track[=XX]");
21263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    When a pointer is freed, do not free the memory right away.");
21363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    Instead, keep XX of these allocations around and then verify");
21463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    that they have not been modified when the total number of freed");
21563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    allocations exceeds the XX amount. When the program terminates,");
2167993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris  error_log("    the rest of these allocations are verified. When this option is");
2177993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris  error_log("    enabled, it automatically records the backtrace at the time of the free.");
218598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  error_log("    The default is to record %zu allocations, the max allocations",
219598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            DEFAULT_FREE_TRACK_ALLOCATIONS);
220598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  error_log("    to record is %zu.", MAX_FREE_TRACK_ALLOCATIONS);
22163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("");
2227993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris  error_log("  free_track_backtrace_num_frames[=XX]");
2237993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris  error_log("    This option only has meaning if free_track is set. This indicates");
2247993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris  error_log("    how many backtrace frames to capture when an allocation is freed.");
2257993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris  error_log("    If XX is set, that is the number of frames to capture. If XX");
2267993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris  error_log("    is set to zero, then no backtrace will be captured.");
227598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  error_log("    The default is to record %zu frames, the max number of frames is %zu.",
228598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            DEFAULT_BACKTRACE_FRAMES, MAX_BACKTRACE_FRAMES);
2297993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris  error_log("");
23063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("  leak_track");
23163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  error_log("    Enable the leak tracking of memory allocations.");
23263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris}
23363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
234166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferrisstatic bool SetFeature(
235166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris    const std::string name, const Feature& feature, size_t value, bool value_set) {
23663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  if (feature.config) {
23763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    *feature.config = true;
23863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  }
23963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  if (feature.value != nullptr) {
24063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    if (value_set) {
241166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris      if (value < feature.min_value) {
242166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris        error_log("%s: bad value for option '%s', value must be >= %zu: %zu",
243166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris                  getprogname(), name.c_str(), feature.min_value, value);
244166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris        return false;
245166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris      } else if (value > feature.max_value) {
246166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris        error_log("%s: bad value for option '%s', value must be <= %zu: %zu",
247166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris                  getprogname(), name.c_str(), feature.max_value, value);
248166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris        return false;
249166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris      }
25063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      *feature.value = value;
25163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    } else {
25263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      *feature.value = feature.default_value;
25363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    }
25463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  } else if (value_set) {
25563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris     error_log("%s: value set for option '%s' which does not take a value",
256166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris               getprogname(), name.c_str());
25763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris     return false;
25863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  }
25963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  return true;
26063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris}
26163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
26263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// This function is designed to be called once. A second call will not
26363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris// reset all variables.
26463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferrisbool Config::SetFromProperties() {
26563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  char property_str[PROP_VALUE_MAX];
26663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  memset(property_str, 0, sizeof(property_str));
26763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  if (!__system_property_get("libc.debug.malloc.options", property_str)) {
26863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    return false;
26963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  }
27063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
27163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  // Initialize a few default values.
272598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  fill_alloc_value = DEFAULT_FILL_ALLOC_VALUE;
273598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  fill_free_value = DEFAULT_FILL_FREE_VALUE;
274598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  front_guard_value = DEFAULT_FRONT_GUARD_VALUE;
275598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris  rear_guard_value = DEFAULT_REAR_GUARD_VALUE;
276258abf70f93ee9231e46111f75cbedbc7cdf4ff9Christopher Ferris  backtrace_signal = SIGRTMAX - 19;
2777993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris  free_track_backtrace_num_frames = 16;
27863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
27963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  // Parse the options are of the format:
28063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  //   option_name or option_name=XX
28163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
28263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  // Supported features:
28363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  const Feature features[] = {
284598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris    Feature("guard", DEFAULT_GUARD_BYTES, 1, MAX_GUARD_BYTES, 0, nullptr, nullptr, true),
28563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Enable front guard. Value is the size of the guard.
286598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris    Feature("front_guard", DEFAULT_GUARD_BYTES, 1, MAX_GUARD_BYTES, FRONT_GUARD,
287598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            &this->front_guard_bytes, nullptr, true),
28863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Enable end guard. Value is the size of the guard.
289598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris    Feature("rear_guard", DEFAULT_GUARD_BYTES, 1, MAX_GUARD_BYTES, REAR_GUARD,
290598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            &this->rear_guard_bytes, nullptr, true),
29163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
29263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Enable logging the backtrace on allocation. Value is the total
29363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // number of frames to log.
294598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris    Feature("backtrace", DEFAULT_BACKTRACE_FRAMES, 1, MAX_BACKTRACE_FRAMES,
295598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            BACKTRACE | TRACK_ALLOCS, &this->backtrace_frames, &this->backtrace_enabled, false),
29663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Enable gathering backtrace values on a signal.
297598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris    Feature("backtrace_enable_on_signal", DEFAULT_BACKTRACE_FRAMES, 1, MAX_BACKTRACE_FRAMES,
298598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            BACKTRACE | TRACK_ALLOCS, &this->backtrace_frames, &this->backtrace_enable_on_signal,
299598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            false),
30063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
301166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris    Feature("fill", SIZE_MAX, 1, SIZE_MAX, 0, nullptr, nullptr, true),
30263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Fill the allocation with an arbitrary pattern on allocation.
30363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Value is the number of bytes of the allocation to fill
30463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // (default entire allocation).
305166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris    Feature("fill_on_alloc", SIZE_MAX, 1, SIZE_MAX, FILL_ON_ALLOC, &this->fill_on_alloc_bytes,
306f2b67b85f5e192812212d3176c07e195c0ffa503Christopher Ferris            nullptr, true),
30763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Fill the allocation with an arbitrary pattern on free.
30863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Value is the number of bytes of the allocation to fill
30963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // (default entire allocation).
310166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris    Feature("fill_on_free", SIZE_MAX, 1, SIZE_MAX, FILL_ON_FREE, &this->fill_on_free_bytes, nullptr, true),
31163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
31263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Expand the size of every alloc by this number bytes. Value is
31363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // the total number of bytes to expand every allocation by.
314598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris    Feature ("expand_alloc", DEFAULT_EXPAND_BYTES, 1, MAX_EXPAND_BYTES, EXPAND_ALLOC,
315598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris             &this->expand_alloc_bytes, nullptr, false),
31663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
31763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Keep track of the freed allocations and verify at a later date
31863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // that they have not been used. Turning this on, also turns on
31963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // fill on free.
320598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris    Feature("free_track", DEFAULT_FREE_TRACK_ALLOCATIONS, 1, MAX_FREE_TRACK_ALLOCATIONS,
321598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            FREE_TRACK | FILL_ON_FREE, &this->free_track_allocations, nullptr, false),
3227993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris    // Number of backtrace frames to keep when free_track is enabled. If this
3237993b80f894db20af4d1d154221c42fea6171a3dChristopher Ferris    // value is set to zero, no backtrace will be kept.
324598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris    Feature("free_track_backtrace_num_frames", DEFAULT_BACKTRACE_FRAMES,
325598e2c0d2ae6b7fbc5eb470e4296c20ed1a011eeChristopher Ferris            0, MAX_BACKTRACE_FRAMES, 0, &this->free_track_backtrace_num_frames, nullptr, false),
32663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
32763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // Enable printing leaked allocations.
328166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris    Feature("leak_track", 0, 0, 0, LEAK_TRACK | TRACK_ALLOCS, nullptr, nullptr, false),
32963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  };
33063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
33163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  // Process each property name we can find.
33263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  std::string property;
33363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  size_t value;
33463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  bool value_set;
33563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  PropertyParser parser(property_str);
33663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  bool valid = true;
33763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  while (valid && parser.Get(&property, &value, &value_set)) {
3384451b53c3761b46fa33a3e47bfb0c62ca47e5fbbChristopher Ferris    bool found = false;
33963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    for (size_t i = 0; i < sizeof(features)/sizeof(Feature); i++) {
34063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      if (property == features[i].name) {
34163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris        if (features[i].option == 0 && features[i].combo_option) {
34263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris          i++;
34363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris          for (; i < sizeof(features)/sizeof(Feature) && features[i].combo_option; i++) {
344166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris            if (!SetFeature(property, features[i], value, value_set)) {
34563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris              valid = false;
34663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris              break;
34763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris            }
34863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris            options |= features[i].option;
34963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris          }
35063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris          if (!valid) {
35163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris            break;
35263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris          }
35363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris        } else {
354166c8535a5a4253bcb2b04bbd20a2a8c04c44f2cChristopher Ferris          if (!SetFeature(property, features[i], value, value_set)) {
35563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris            valid = false;
35663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris            break;
35763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris          }
35863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris          options |= features[i].option;
35963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris        }
36063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris        found = true;
36163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris        break;
36263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      }
36363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    }
36463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    if (valid && !found) {
36563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      error_log("%s: unknown option %s", getprogname(), property.c_str());
36663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      valid = false;
36763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      break;
36863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    }
36963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  }
37063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
37163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  valid = valid && parser.Done();
37263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
37363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  if (valid) {
37439b952cf0a824db1cdc301dd048db0e56d4d5c24Christopher Ferris    // It's necessary to align the front guard to MINIMUM_ALIGNMENT_BYTES to
37563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // make sure that the header is aligned properly.
37663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    if (options & FRONT_GUARD) {
37739b952cf0a824db1cdc301dd048db0e56d4d5c24Christopher Ferris      front_guard_bytes = BIONIC_ALIGN(front_guard_bytes, MINIMUM_ALIGNMENT_BYTES);
37863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    }
37963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
38063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // This situation can occur if the free_track option is specified and
38163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // the fill_on_free option is not. In this case, indicate the whole
38263860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    // allocation should be filled.
38363860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    if ((options & FILL_ON_FREE) && fill_on_free_bytes == 0) {
38463860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris      fill_on_free_bytes = SIZE_MAX;
38563860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    }
38663860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  } else {
38763860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris    parser.LogUsage();
38863860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  }
38963860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris
39063860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris  return valid;
39163860cb8fd1adf3f679b9b4ad876323a8d65cd9dChristopher Ferris}
392