folly: build with -Wunused-parameter
[folly.git] / folly / experimental / symbolizer / Dwarf.cpp
index 4ce3c974f3513f952ffa6ffef0c1c345a2f35519..28da29c7a3c955a161d6dcb6f7104b9d4a9f9803 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2015 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
  */
 
 
-#include "folly/experimental/symbolizer/Dwarf.h"
+#include <folly/experimental/symbolizer/Dwarf.h>
 
 #include <type_traits>
 
@@ -131,6 +131,10 @@ void simplifyPath(folly::StringPiece& sp) {
     }
 
     if (sp.removePrefix("./")) {
+      // Also remove any subsequent slashes to avoid making this path absolute.
+      while (sp.startsWith('/')) {
+        sp.advance(1);
+      }
       continue;
     }
 
@@ -143,8 +147,8 @@ void simplifyPath(folly::StringPiece& sp) {
       return;
     }
 
-    // Strip trailing slashes
-    while (sp.removeSuffix('/')) { }
+    // Strip trailing slashes, except when this is the root path.
+    while (sp.size() > 1 && sp.removeSuffix('/')) { }
 
     if (sp.removeSuffix("/.")) {
       continue;
@@ -180,29 +184,42 @@ Dwarf::Path::Path(folly::StringPiece baseDir, folly::StringPiece subDir,
     baseDir_.clear();  // subDir_ is absolute
   }
 
-  // Make sure that baseDir_ isn't empty; subDir_ may be
-  if (baseDir_.empty()) {
-    swap(baseDir_, subDir_);
-  }
-
   simplifyPath(baseDir_);
   simplifyPath(subDir_);
   simplifyPath(file_);
+
+  // Make sure it's never the case that baseDir_ is empty, but subDir_ isn't.
+  if (baseDir_.empty()) {
+    swap(baseDir_, subDir_);
+  }
 }
 
 size_t Dwarf::Path::size() const {
-  if (baseDir_.empty()) {
-    assert(subDir_.empty());
-    return file_.size();
+  size_t size = 0;
+  bool needsSlash = false;
+
+  if (!baseDir_.empty()) {
+    size += baseDir_.size();
+    needsSlash = !baseDir_.endsWith('/');
   }
 
-  return
-    baseDir_.size() + !subDir_.empty() + subDir_.size() + !file_.empty() +
-    file_.size();
+  if (!subDir_.empty()) {
+    size += needsSlash;
+    size += subDir_.size();
+    needsSlash = !subDir_.endsWith('/');
+  }
+
+  if (!file_.empty()) {
+    size += needsSlash;
+    size += file_.size();
+  }
+
+  return size;
 }
 
 size_t Dwarf::Path::toBuffer(char* buf, size_t bufSize) const {
   size_t totalSize = 0;
+  bool needsSlash = false;
 
   auto append = [&] (folly::StringPiece sp) {
     if (bufSize >= 2) {
@@ -216,14 +233,17 @@ size_t Dwarf::Path::toBuffer(char* buf, size_t bufSize) const {
 
   if (!baseDir_.empty()) {
     append(baseDir_);
+    needsSlash = !baseDir_.endsWith('/');
   }
   if (!subDir_.empty()) {
-    assert(!baseDir_.empty());
-    append("/");
+    if (needsSlash) {
+      append("/");
+    }
     append(subDir_);
+    needsSlash = !subDir_.endsWith('/');
   }
   if (!file_.empty()) {
-    if (!baseDir_.empty()) {
+    if (needsSlash) {
       append("/");
     }
     append(file_);
@@ -242,12 +262,15 @@ void Dwarf::Path::toString(std::string& dest) const {
     dest.append(baseDir_.begin(), baseDir_.end());
   }
   if (!subDir_.empty()) {
-    assert(!baseDir_.empty());
-    dest.push_back('/');
+    if (!dest.empty() && dest.back() != '/') {
+      dest.push_back('/');
+    }
     dest.append(subDir_.begin(), subDir_.end());
   }
   if (!file_.empty()) {
-    dest.push_back('/');
+    if (!dest.empty() && dest.back() != '/') {
+      dest.push_back('/');
+    }
     dest.append(file_.begin(), file_.end());
   }
   assert(dest.size() == initialSize + size());
@@ -852,4 +875,3 @@ bool Dwarf::LineNumberVM::findAddress(uintptr_t target, Path& file,
 
 }  // namespace symbolizer
 }  // namespace folly
-