aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Saleem Abdulrasool <compnerd@compnerd.org> 2012-12-04 20:01:25 -0800
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2012-12-05 18:57:15 +0000
commit54d022937f6a6ffe8471aae28ffdc68ece352dff (patch)
tree364e98efd9bbe1e1642678298005003db54211dc
parentcb1b7137a7ce1de0df29d8427dfb0525b7a89c7e (diff)
downloadpaludis-54d022937f6a6ffe8471aae28ffdc68ece352dff.tar.gz
paludis-54d022937f6a6ffe8471aae28ffdc68ece352dff.tar.xz
stripper: add support to compress DWARF sections
This adds a new dwarf_compress build option to use dwz to compress the DWARF information in executables and libraries. Use of this functionality requires the dwz package to be installed and available in the default path. Enabling this during builds can reduce the size of the *compressed* symbols by an additional ~10-25%.
-rw-r--r--paludis/elike_choices-fwd.hh1
-rw-r--r--paludis/elike_choices.cc83
-rw-r--r--paludis/elike_choices.hh44
-rw-r--r--paludis/repositories/e/do_install_action.cc3
-rw-r--r--paludis/repositories/e/e_stripper.cc9
-rw-r--r--paludis/repositories/e/e_stripper.hh3
-rw-r--r--paludis/repositories/e/ebuild_id.cc5
-rw-r--r--paludis/repositories/unpackaged/unpackaged_id.cc2
-rw-r--r--paludis/repositories/unpackaged/unpackaged_key.cc4
-rw-r--r--paludis/repositories/unpackaged/unpackaged_stripper.cc9
-rw-r--r--paludis/repositories/unpackaged/unpackaged_stripper.hh3
-rw-r--r--paludis/stripper.cc28
-rw-r--r--paludis/stripper.hh5
-rw-r--r--paludis/stripper_TEST.cc5
14 files changed, 203 insertions, 1 deletions
diff --git a/paludis/elike_choices-fwd.hh b/paludis/elike_choices-fwd.hh
index bb0bae6..f176d62 100644
--- a/paludis/elike_choices-fwd.hh
+++ b/paludis/elike_choices-fwd.hh
@@ -35,6 +35,7 @@ namespace paludis
struct ELikeTraceChoiceValue;
struct ELikeSymbolsChoiceValue;
struct ELikeWorkChoiceValue;
+ struct ELikeDwarfCompressionChoiceValue;
const ChoicePrefixName canonical_build_options_prefix() PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
const std::string canonical_build_options_raw_name() PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
diff --git a/paludis/elike_choices.cc b/paludis/elike_choices.cc
index 6196ef6..805963c 100644
--- a/paludis/elike_choices.cc
+++ b/paludis/elike_choices.cc
@@ -868,3 +868,86 @@ ELikeWorkChoiceValue::should_remove_on_failure(const std::string & v)
throw InternalError(PALUDIS_HERE, "Unhandled ELikeWorkChoiceValueParameter");
}
+// ELikeDwarfCompressionChoiceValue
+
+const UnprefixedChoiceName
+ELikeDwarfCompressionChoiceValue::canonical_unprefixed_name()
+{
+ return UnprefixedChoiceName("dwarf_compress");
+}
+
+const ChoiceNameWithPrefix
+ELikeDwarfCompressionChoiceValue::canonical_name_with_prefix()
+{
+ return ChoiceNameWithPrefix(stringify(canonical_build_options_prefix())
+ + ":" +
+ stringify(canonical_unprefixed_name()));
+}
+
+ELikeDwarfCompressionChoiceValue::ELikeDwarfCompressionChoiceValue(const std::shared_ptr<const PackageID> & id,
+ const Environment * const env,
+ const std::shared_ptr<const Choice> & choice)
+ : _enabled(env->want_choice_enabled(id, choice, canonical_unprefixed_name()).is_true())
+{
+}
+
+const UnprefixedChoiceName
+ELikeDwarfCompressionChoiceValue::unprefixed_name() const
+{
+ return canonical_unprefixed_name();
+}
+
+const ChoiceNameWithPrefix
+ELikeDwarfCompressionChoiceValue::name_with_prefix() const
+{
+ return canonical_name_with_prefix();
+}
+
+bool
+ELikeDwarfCompressionChoiceValue::enabled() const
+{
+ return _enabled;
+}
+
+bool
+ELikeDwarfCompressionChoiceValue::enabled_by_default() const
+{
+ return false;
+}
+
+bool
+ELikeDwarfCompressionChoiceValue::presumed() const
+{
+ return false;
+}
+
+bool
+ELikeDwarfCompressionChoiceValue::locked() const
+{
+ return false;
+}
+
+const std::string
+ELikeDwarfCompressionChoiceValue::description() const
+{
+ return "Compress DWARF2+ debug information";
+}
+
+ChoiceOrigin
+ELikeDwarfCompressionChoiceValue::origin() const
+{
+ return co_special;
+}
+
+const std::string
+ELikeDwarfCompressionChoiceValue::parameter() const
+{
+ return "";
+}
+
+const std::shared_ptr<const PermittedChoiceValueParameterValues>
+ELikeDwarfCompressionChoiceValue::permitted_parameter_values() const
+{
+ return make_null_shared_ptr();
+}
+
diff --git a/paludis/elike_choices.hh b/paludis/elike_choices.hh
index 60a237a..01d1b0e 100644
--- a/paludis/elike_choices.hh
+++ b/paludis/elike_choices.hh
@@ -229,6 +229,50 @@ namespace paludis
static bool should_remove_on_failure(const std::string &) PALUDIS_ATTRIBUTE((warn_unused_result));
static bool should_merge_nondestructively(const std::string &) PALUDIS_ATTRIBUTE((warn_unused_result));
};
+
+ class PALUDIS_VISIBLE ELikeDwarfCompressionChoiceValue :
+ public ChoiceValue
+ {
+ private:
+ bool _enabled;
+
+ public:
+ ELikeDwarfCompressionChoiceValue(const std::shared_ptr<const PackageID> &,
+ const Environment * const,
+ const std::shared_ptr<const Choice> &);
+
+ ///\name Properties
+ ///\{
+
+ virtual const UnprefixedChoiceName unprefixed_name() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const ChoiceNameWithPrefix name_with_prefix() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual bool enabled() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual bool enabled_by_default() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual bool presumed() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual bool locked() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const std::string description() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual ChoiceOrigin origin() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const std::string parameter() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ virtual const std::shared_ptr<const PermittedChoiceValueParameterValues> permitted_parameter_values() const
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ /// \}
+
+ static const UnprefixedChoiceName canonical_unprefixed_name()
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ static const ChoiceNameWithPrefix canonical_name_with_prefix()
+ PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
}
#endif
+
diff --git a/paludis/repositories/e/do_install_action.cc b/paludis/repositories/e/do_install_action.cc
index 72f90a6..5439b31 100644
--- a/paludis/repositories/e/do_install_action.cc
+++ b/paludis/repositories/e/do_install_action.cc
@@ -310,10 +310,13 @@ paludis::erepository::do_install_action(
std::shared_ptr<const ChoiceValue> symbols_choice(choices->find_by_name_with_prefix(
ELikeSymbolsChoiceValue::canonical_name_with_prefix()));
+ auto dwarf_compression(choices->find_by_name_with_prefix(ELikeDwarfCompressionChoiceValue::canonical_name_with_prefix()));
+
EStripper stripper(make_named_values<EStripperOptions>(
n::compress_splits() = symbols_choice && symbols_choice->enabled() && ELikeSymbolsChoiceValue::should_compress(
symbols_choice->parameter()),
n::debug_dir() = package_builddir / "image" / "usr" / libdir / "debug",
+ n::dwarf_compression() = dwarf_compression && dwarf_compression->enabled(),
n::image_dir() = package_builddir / "image",
n::output_manager() = output_manager,
n::package_id() = id,
diff --git a/paludis/repositories/e/e_stripper.cc b/paludis/repositories/e/e_stripper.cc
index 878d545..053e059 100644
--- a/paludis/repositories/e/e_stripper.cc
+++ b/paludis/repositories/e/e_stripper.cc
@@ -44,6 +44,7 @@ EStripper::EStripper(const EStripperOptions & options) :
Stripper(make_named_values<StripperOptions>(
n::compress_splits() = options.compress_splits(),
n::debug_dir() = options.debug_dir(),
+ n::dwarf_compression() = options.dwarf_compression(),
n::image_dir() = options.image_dir(),
n::split() = options.split(),
n::strip() = options.strip()
@@ -84,6 +85,14 @@ EStripper::on_split(const FSPath & f, const FSPath & g)
}
void
+EStripper::on_dwarf_compress(const FSPath & f)
+{
+ _imp->options.output_manager()->stdout_stream()
+ << dwarf_compress_desc() << " "
+ << f.strip_leading(_imp->options.image_dir()) << std::endl;
+}
+
+void
EStripper::on_unknown(const FSPath & f)
{
_imp->options.output_manager()->stdout_stream()
diff --git a/paludis/repositories/e/e_stripper.hh b/paludis/repositories/e/e_stripper.hh
index 80c9e78..810cc03 100644
--- a/paludis/repositories/e/e_stripper.hh
+++ b/paludis/repositories/e/e_stripper.hh
@@ -31,6 +31,7 @@ namespace paludis
{
typedef Name<struct name_compress_splits> compress_splits;
typedef Name<struct name_debug_dir> debug_dir;
+ typedef Name<struct name_dwarf_compression> dwarf_compression;
typedef Name<struct name_image_dir> image_dir;
typedef Name<struct name_output_manager> output_manager;
typedef Name<struct name_package_id> package_id;
@@ -44,6 +45,7 @@ namespace paludis
{
NamedValue<n::compress_splits, bool> compress_splits;
NamedValue<n::debug_dir, FSPath> debug_dir;
+ NamedValue<n::dwarf_compression, bool> dwarf_compression;
NamedValue<n::image_dir, FSPath> image_dir;
NamedValue<n::output_manager, std::shared_ptr<OutputManager> > output_manager;
NamedValue<n::package_id, std::shared_ptr<const PackageID> > package_id;
@@ -63,6 +65,7 @@ namespace paludis
virtual void on_strip(const FSPath &);
virtual void on_split(const FSPath &, const FSPath &);
+ virtual void on_dwarf_compress(const FSPath &);
virtual void on_unknown(const FSPath &);
public:
diff --git a/paludis/repositories/e/ebuild_id.cc b/paludis/repositories/e/ebuild_id.cc
index 6a849aa..e029f28 100644
--- a/paludis/repositories/e/ebuild_id.cc
+++ b/paludis/repositories/e/ebuild_id.cc
@@ -1677,6 +1677,11 @@ EbuildID::add_build_options(const std::shared_ptr<Choices> & choices) const
mask_expensive_tests = true;
}
+ /* dwarf compression */
+ build_options->add(std::make_shared<ELikeDwarfCompressionChoiceValue>(shared_from_this(),
+ _imp->environment,
+ build_options));
+
/* optional_tests */
if (eapi()->supported()->choices_options()->has_optional_tests())
build_options->add(std::make_shared<ELikeOptionalTestsChoiceValue>(shared_from_this(), _imp->environment, build_options,
diff --git a/paludis/repositories/unpackaged/unpackaged_id.cc b/paludis/repositories/unpackaged/unpackaged_id.cc
index a1524c4..284bbab 100644
--- a/paludis/repositories/unpackaged/unpackaged_id.cc
+++ b/paludis/repositories/unpackaged/unpackaged_id.cc
@@ -371,6 +371,7 @@ UnpackagedID::perform_action(Action & action) const
auto choices(choices_key()->parse_value());
auto symbols_choice(choices->find_by_name_with_prefix(ELikeSymbolsChoiceValue::canonical_name_with_prefix()));
auto work_choice(choices->find_by_name_with_prefix(ELikeWorkChoiceValue::canonical_name_with_prefix()));
+ auto dwarf_compression(choices->find_by_name_with_prefix(ELikeDwarfCompressionChoiceValue::canonical_name_with_prefix()));
std::string used_config_protect;
@@ -382,6 +383,7 @@ UnpackagedID::perform_action(Action & action) const
n::compress_splits() = symbols_choice && symbols_choice->enabled() && ELikeSymbolsChoiceValue::should_compress(
symbols_choice->parameter()),
n::debug_dir() = fs_location_key()->parse_value() / "usr" / libdir / "debug",
+ n::dwarf_compression() = dwarf_compression && dwarf_compression->enabled(),
n::image_dir() = fs_location_key()->parse_value(),
n::output_manager() = output_manager,
n::package_id() = shared_from_this(),
diff --git a/paludis/repositories/unpackaged/unpackaged_key.cc b/paludis/repositories/unpackaged/unpackaged_key.cc
index 457604a..67e56db 100644
--- a/paludis/repositories/unpackaged/unpackaged_key.cc
+++ b/paludis/repositories/unpackaged/unpackaged_key.cc
@@ -171,6 +171,10 @@ UnpackagedChoicesKey::parse_value() const
build_options->add(std::make_shared<ELikeSymbolsChoiceValue>(_imp->id->shared_from_this(), _imp->env, build_options,
strip.is_true() ? escvp_strip : strip.is_false() ? escvp_preserve : last_escvp));
+ build_options->add(std::make_shared<ELikeDwarfCompressionChoiceValue>(_imp->id->shared_from_this(),
+ _imp->env,
+ build_options));
+
ELikeWorkChoiceValueParameter preserve_work(last_ewcvp);
if (_imp->id->preserve_work_key())
preserve_work = _imp->id->preserve_work_key()->parse_value() ? ewcvp_preserve : ewcvp_leave;
diff --git a/paludis/repositories/unpackaged/unpackaged_stripper.cc b/paludis/repositories/unpackaged/unpackaged_stripper.cc
index e671fd8..49e086b 100644
--- a/paludis/repositories/unpackaged/unpackaged_stripper.cc
+++ b/paludis/repositories/unpackaged/unpackaged_stripper.cc
@@ -44,6 +44,7 @@ UnpackagedStripper::UnpackagedStripper(const UnpackagedStripperOptions & options
Stripper(make_named_values<StripperOptions>(
n::compress_splits() = options.compress_splits(),
n::debug_dir() = options.debug_dir(),
+ n::dwarf_compression() = options.dwarf_compression(),
n::image_dir() = options.image_dir(),
n::split() = options.split(),
n::strip() = options.strip()
@@ -84,6 +85,14 @@ UnpackagedStripper::on_split(const FSPath & f, const FSPath & g)
}
void
+UnpackagedStripper::on_dwarf_compress(const FSPath & f)
+{
+ _imp->options.output_manager()->stdout_stream()
+ << dwarf_compress_desc() << " "
+ << f.strip_leading(_imp->options.image_dir()) << std::endl;
+}
+
+void
UnpackagedStripper::on_unknown(const FSPath & f)
{
_imp->options.output_manager()->stdout_stream()
diff --git a/paludis/repositories/unpackaged/unpackaged_stripper.hh b/paludis/repositories/unpackaged/unpackaged_stripper.hh
index cc13622..6f48fa5 100644
--- a/paludis/repositories/unpackaged/unpackaged_stripper.hh
+++ b/paludis/repositories/unpackaged/unpackaged_stripper.hh
@@ -31,6 +31,7 @@ namespace paludis
{
typedef Name<struct name_compress_splits> compress_splits;
typedef Name<struct name_debug_dir> debug_dir;
+ typedef Name<struct name_dwarf_compression> dwarf_compression;
typedef Name<struct name_image_dir> image_dir;
typedef Name<struct name_output_manager> output_manager;
typedef Name<struct name_package_id> package_id;
@@ -44,6 +45,7 @@ namespace paludis
{
NamedValue<n::compress_splits, bool> compress_splits;
NamedValue<n::debug_dir, FSPath> debug_dir;
+ NamedValue<n::dwarf_compression, bool> dwarf_compression;
NamedValue<n::image_dir, FSPath> image_dir;
NamedValue<n::output_manager, std::shared_ptr<OutputManager> > output_manager;
NamedValue<n::package_id, std::shared_ptr<const PackageID> > package_id;
@@ -63,6 +65,7 @@ namespace paludis
virtual void on_strip(const FSPath &);
virtual void on_split(const FSPath &, const FSPath &);
+ virtual void on_dwarf_compress(const FSPath &);
virtual void on_unknown(const FSPath &);
public:
diff --git a/paludis/stripper.cc b/paludis/stripper.cc
index bc3a8c3..0c5084b 100644
--- a/paludis/stripper.cc
+++ b/paludis/stripper.cc
@@ -201,6 +201,8 @@ Stripper::do_dir_recursive(const FSPath & f)
std::string t(file_type(*d));
if (std::string::npos != t.find("SB executable") || std::string::npos != t.find("SB shared object"))
{
+ if (_imp->options.dwarf_compression())
+ do_dwarf_compress(*d);
if (_imp->options.split())
{
FSPath target(_imp->options.debug_dir() / d->strip_leading(_imp->options.image_dir()));
@@ -282,6 +284,19 @@ Stripper::do_split(const FSPath & f, const FSPath & g)
g.chmod(g.stat().permissions() & ~(S_IXGRP | S_IXUSR | S_IXOTH | S_IWOTH));
}
+void
+Stripper::do_dwarf_compress(const FSPath & f)
+{
+ Context context("When compressing DWARF information for '" + stringify(f) + "'");
+
+ on_dwarf_compress(f);
+
+ Process dwz_process(ProcessCommand({ "dwz", /* quiet => */ "-q", stringify(f) }));
+ if (dwz_process.run().wait() != 0)
+ Log::get_instance()->message("strip.failure", ll_warning, lc_context)
+ << "Couldn't compress DWARF information for '" << f << "'";
+}
+
std::string
Stripper::strip_action_desc() const
{
@@ -291,7 +306,12 @@ Stripper::strip_action_desc() const
std::string
Stripper::split_action_desc() const
{
- return (_imp->options.compress_splits() ? "spz" : "spl");
+ const char desc[3] = {
+ _imp->options.dwarf_compression() ? 'd' : 's',
+ 'p',
+ _imp->options.compress_splits() ? 'z' : 'l',
+ };
+ return std::string(desc, sizeof(desc));
}
std::string
@@ -300,3 +320,9 @@ Stripper::unknown_action_desc() const
return "---";
}
+std::string
+Stripper::dwarf_compress_desc() const
+{
+ return "dwz";
+}
+
diff --git a/paludis/stripper.hh b/paludis/stripper.hh
index d4af5c2..df6088d 100644
--- a/paludis/stripper.hh
+++ b/paludis/stripper.hh
@@ -34,6 +34,7 @@ namespace paludis
{
typedef Name<struct name_compress_splits> compress_splits;
typedef Name<struct name_debug_dir> debug_dir;
+ typedef Name<struct name_dwarf_compression> dwarf_compression;
typedef Name<struct name_image_dir> image_dir;
typedef Name<struct name_split> split;
typedef Name<struct name_strip> strip;
@@ -43,6 +44,7 @@ namespace paludis
{
NamedValue<n::compress_splits, bool> compress_splits;
NamedValue<n::debug_dir, FSPath> debug_dir;
+ NamedValue<n::dwarf_compression, bool> dwarf_compression;
NamedValue<n::image_dir, FSPath> image_dir;
NamedValue<n::split, bool> split;
NamedValue<n::strip, bool> strip;
@@ -66,6 +68,7 @@ namespace paludis
virtual void on_strip(const FSPath &) = 0;
virtual void on_split(const FSPath &, const FSPath &) = 0;
+ virtual void on_dwarf_compress(const FSPath &) = 0;
virtual void on_unknown(const FSPath &) = 0;
virtual void do_dir_recursive(const FSPath &);
@@ -74,10 +77,12 @@ namespace paludis
virtual void do_split(const FSPath &, const FSPath &);
virtual void do_strip(const FSPath &, const std::string &);
+ virtual void do_dwarf_compress(const FSPath &);
virtual std::string strip_action_desc() const;
virtual std::string split_action_desc() const;
virtual std::string unknown_action_desc() const;
+ virtual std::string dwarf_compress_desc() const;
public:
///\name Basic operations
diff --git a/paludis/stripper_TEST.cc b/paludis/stripper_TEST.cc
index bfbb3bc..7bd54b2 100644
--- a/paludis/stripper_TEST.cc
+++ b/paludis/stripper_TEST.cc
@@ -50,6 +50,10 @@ namespace
{
}
+ virtual void on_dwarf_compress(const FSPath &)
+ {
+ }
+
virtual void on_unknown(const FSPath &)
{
}
@@ -66,6 +70,7 @@ TEST(Stripper, Works)
TestStripper s(make_named_values<StripperOptions>(
n::compress_splits() = false,
n::debug_dir() = FSPath("stripper_TEST_dir/image").realpath() / "usr" / "lib" / "debug",
+ n::dwarf_compression() = false,
n::image_dir() = FSPath("stripper_TEST_dir/image").realpath(),
n::split() = true,
n::strip() = true