diff --git a/src/google_breakpad/processor/fast_source_line_resolver.h b/src/google_breakpad/processor/fast_source_line_resolver.h
index fdf91077..535fc106 100644
--- a/src/google_breakpad/processor/fast_source_line_resolver.h
+++ b/src/google_breakpad/processor/fast_source_line_resolver.h
@@ -79,6 +79,8 @@ class FastSourceLineResolver : public SourceLineResolverBase {
   // SourceLineResolverBase.
   struct Line;
   struct Function;
+  struct Inline;
+  struct InlineOrigin;
   struct PublicSymbol;
   class Module;
 
diff --git a/src/processor/fast_source_line_resolver.cc b/src/processor/fast_source_line_resolver.cc
index 31786460..374b06cf 100644
--- a/src/processor/fast_source_line_resolver.cc
+++ b/src/processor/fast_source_line_resolver.cc
@@ -49,9 +49,8 @@
 #include "processor/module_factory.h"
 #include "processor/simple_serializer-inl.h"
 
-using std::map;
-using std::make_pair;
-using std::vector;
+using std::deque;
+using std::unique_ptr;
 
 namespace google_breakpad {
 
@@ -101,6 +100,10 @@ void FastSourceLineResolver::Module::LookupAddress(
       frame->source_line = line->line;
       frame->source_line_base = frame->module->base_address() + line_base;
     }
+    // Check if this is inlined function call.
+    if (inlined_frames) {
+      ConstructInlineFrames(frame, address, func->inlines, inlined_frames);
+    }
   } else if (public_symbols_.Retrieve(address,
                                       public_symbol_ptr, &public_address) &&
              (!func_ptr || public_address > function_base)) {
@@ -110,6 +113,68 @@ void FastSourceLineResolver::Module::LookupAddress(
   }
 }
 
+void FastSourceLineResolver::Module::ConstructInlineFrames(
+    StackFrame* frame,
+    MemAddr address,
+    const StaticContainedRangeMap<MemAddr, char>& inline_map,
+    std::deque<std::unique_ptr<StackFrame>>* inlined_frames) const {
+  std::vector<const char*> inline_ptrs;
+  if (!inline_map.RetrieveRanges(address, inline_ptrs)) {
+    return;
+  }
+
+  for (const char* inline_ptr : inline_ptrs) {
+    scoped_ptr<Inline> in(new Inline);
+    in.get()->CopyFrom(inline_ptr);
+    unique_ptr<StackFrame> new_frame =
+        unique_ptr<StackFrame>(new StackFrame(*frame));
+    auto origin_iter = inline_origins_.find(in->origin_id);
+    if (origin_iter != inline_origins_.end()) {
+      scoped_ptr<InlineOrigin> origin(new InlineOrigin);
+      origin.get()->CopyFrom(origin_iter.GetValuePtr());
+      new_frame->function_name = origin->name;
+    } else {
+      new_frame->function_name = "<name omitted>";
+    }
+
+    // Store call site file and line in current frame, which will be updated
+    // later.
+    new_frame->source_line = in->call_site_line;
+    if (in->has_call_site_file_id) {
+      auto file_iter = files_.find(in->call_site_file_id);
+      if (file_iter != files_.end()) {
+        new_frame->source_file_name = file_iter.GetValuePtr();
+      }
+    }
+
+    // Use the starting adress of the inlined range as inlined function base.
+    new_frame->function_base = new_frame->module->base_address();
+    for (const auto& range : in->inline_ranges) {
+      if (address >= range.first && address < range.first + range.second) {
+        new_frame->function_base += range.first;
+        break;
+      }
+    }
+    new_frame->trust = StackFrame::FRAME_TRUST_INLINE;
+
+    // The inlines vector has an order from innermost entry to outermost entry.
+    // By push_back, we will have inlined_frames with the same order.
+    inlined_frames->push_back(std::move(new_frame));
+  }
+
+  // Update the source file and source line for each inlined frame.
+  if (!inlined_frames->empty()) {
+    string parent_frame_source_file_name = frame->source_file_name;
+    int parent_frame_source_line = frame->source_line;
+    frame->source_file_name = inlined_frames->back()->source_file_name;
+    frame->source_line = inlined_frames->back()->source_line;
+    for (unique_ptr<StackFrame>& inlined_frame : *inlined_frames) {
+      std::swap(inlined_frame->source_file_name, parent_frame_source_file_name);
+      std::swap(inlined_frame->source_line, parent_frame_source_line);
+    }
+  }
+}
+
 // WFI: WindowsFrameInfo.
 // Returns a WFI object reading from a raw memory chunk of data
 WindowsFrameInfo FastSourceLineResolver::CopyWFI(const char* raw) {
@@ -184,7 +249,7 @@ bool FastSourceLineResolver::Module::LoadMapFromMemory(
   cfi_initial_rules_ =
       StaticRangeMap<MemAddr, char>(mem_buffer + offsets[map_id++]);
   cfi_delta_rules_ = StaticMap<MemAddr, char>(mem_buffer + offsets[map_id++]);
-
+  inline_origins_ = StaticMap<int, char>(mem_buffer + offsets[map_id++]);
   return true;
 }
 
diff --git a/src/processor/fast_source_line_resolver_types.h b/src/processor/fast_source_line_resolver_types.h
index 2d1bcfcb..577b98e6 100644
--- a/src/processor/fast_source_line_resolver_types.h
+++ b/src/processor/fast_source_line_resolver_types.h
@@ -37,6 +37,7 @@
 #ifndef PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__
 #define PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__
 
+#include "contained_range_map.h"
 #include "google_breakpad/processor/fast_source_line_resolver.h"
 #include "processor/source_line_resolver_base_types.h"
 
@@ -53,6 +54,10 @@
 
 namespace google_breakpad {
 
+#define DESERIALIZE(raw_ptr, field)                             \
+  field = *(reinterpret_cast<const decltype(field)*>(raw_ptr)); \
+  raw_ptr += sizeof(field);
+
 struct FastSourceLineResolver::Line : public SourceLineResolverBase::Line {
   void CopyFrom(const Line* line_ptr) {
     const char* raw = reinterpret_cast<const char*>(line_ptr);
@@ -61,12 +66,10 @@ struct FastSourceLineResolver::Line : public SourceLineResolverBase::Line {
 
   // De-serialize the memory data of a Line.
   void CopyFrom(const char* raw) {
-    address = *(reinterpret_cast<const MemAddr*>(raw));
-    size = *(reinterpret_cast<const MemAddr*>(raw + sizeof(address)));
-    source_file_id = *(reinterpret_cast<const int32_t*>(
-        raw + 2 * sizeof(address)));
-    line = *(reinterpret_cast<const int32_t*>(
-        raw + 2 * sizeof(address) + sizeof(source_file_id)));
+    DESERIALIZE(raw, address);
+    DESERIALIZE(raw, size);
+    DESERIALIZE(raw, source_file_id);
+    DESERIALIZE(raw, line);
   }
 };
 
@@ -81,18 +84,60 @@ public SourceLineResolverBase::Function {
   void CopyFrom(const char* raw) {
     size_t name_size = strlen(raw) + 1;
     name = raw;
-    address = *(reinterpret_cast<const MemAddr*>(raw + name_size));
-    size = *(reinterpret_cast<const MemAddr*>(
-        raw + name_size + sizeof(MemAddr)));
-    parameter_size = *(reinterpret_cast<const int32_t*>(
-        raw + name_size + 2 * sizeof(MemAddr)));
-    lines = StaticRangeMap<MemAddr, Line>(
-        raw + name_size + 2 * sizeof(MemAddr) + sizeof(int32_t));
+    raw += name_size;
+    DESERIALIZE(raw, address);
+    DESERIALIZE(raw, size);
+    DESERIALIZE(raw, parameter_size);
+    DESERIALIZE(raw, is_multiple);
+    int32_t inline_size;
+    DESERIALIZE(raw, inline_size);
+    inlines = StaticContainedRangeMap<MemAddr, char>(raw);
+    lines = StaticRangeMap<MemAddr, Line>(raw + inline_size);
   }
 
+  StaticContainedRangeMap<MemAddr, char> inlines;
   StaticRangeMap<MemAddr, Line> lines;
 };
 
+struct FastSourceLineResolver::Inline : public SourceLineResolverBase::Inline {
+  void CopyFrom(const Inline* inline_ptr) {
+    const char* raw = reinterpret_cast<const char*>(inline_ptr);
+    CopyFrom(raw);
+  }
+
+  // De-serialize the memory data of a Inline.
+  void CopyFrom(const char* raw) {
+    DESERIALIZE(raw, has_call_site_file_id);
+    DESERIALIZE(raw, inline_nest_level);
+    DESERIALIZE(raw, call_site_line);
+    DESERIALIZE(raw, call_site_file_id);
+    DESERIALIZE(raw, origin_id);
+    uint32_t inline_range_size;
+    DESERIALIZE(raw, inline_range_size);
+    for (size_t i = 0; i < inline_range_size; i += 2) {
+      std::pair<MemAddr, MemAddr> range;
+      DESERIALIZE(raw, range.first);
+      DESERIALIZE(raw, range.second);
+      inline_ranges.push_back(range);
+    }
+  }
+};
+
+struct FastSourceLineResolver::InlineOrigin
+    : public SourceLineResolverBase::InlineOrigin {
+  void CopyFrom(const InlineOrigin* origin_ptr) {
+    const char* raw = reinterpret_cast<const char*>(origin_ptr);
+    CopyFrom(raw);
+  }
+
+  // De-serialize the memory data of a Line.
+  void CopyFrom(const char* raw) {
+    DESERIALIZE(raw, has_file_id);
+    DESERIALIZE(raw, source_file_id);
+    name = raw;
+  }
+};
+
 struct FastSourceLineResolver::PublicSymbol :
 public SourceLineResolverBase::PublicSymbol {
   void CopyFrom(const PublicSymbol* public_symbol_ptr) {
@@ -104,12 +149,15 @@ public SourceLineResolverBase::PublicSymbol {
   void CopyFrom(const char* raw) {
     size_t name_size = strlen(raw) + 1;
     name = raw;
-    address = *(reinterpret_cast<const MemAddr*>(raw + name_size));
-    parameter_size = *(reinterpret_cast<const int32_t*>(
-        raw + name_size + sizeof(MemAddr)));
+    raw += name_size;
+    DESERIALIZE(raw, address);
+    DESERIALIZE(raw, parameter_size);
+    DESERIALIZE(raw, is_multiple);
   }
 };
 
+#undef DESERIALIZE
+
 class FastSourceLineResolver::Module: public SourceLineResolverBase::Module {
  public:
   explicit Module(const string& name) : name_(name), is_corrupt_(false) { }
@@ -121,6 +169,16 @@ class FastSourceLineResolver::Module: public SourceLineResolverBase::Module {
       StackFrame* frame,
       std::deque<std::unique_ptr<StackFrame>>* inlined_frames) const;
 
+  // Construct inlined frames for |frame| and store them in |inline_frames|.
+  // |frame|'s source line and source file name may be updated if an inlined
+  // frame is found inside |frame|. As a result, the innermost inlined frame
+  // will be the first one in |inline_frames|.
+  virtual void ConstructInlineFrames(
+      StackFrame* frame,
+      MemAddr address,
+      const StaticContainedRangeMap<MemAddr, char>& inline_map,
+      std::deque<std::unique_ptr<StackFrame>>* inlined_frames) const;
+
   // Loads a map from the given buffer in char* type.
   virtual bool LoadMapFromMemory(char* memory_buffer,
                                  size_t memory_buffer_size);
@@ -143,7 +201,7 @@ class FastSourceLineResolver::Module: public SourceLineResolverBase::Module {
   virtual CFIFrameInfo* FindCFIFrameInfo(const StackFrame* frame) const;
 
   // Number of serialized map components of Module.
-  static const int kNumberMaps_ = 5 + WindowsFrameInfo::STACK_INFO_LAST;
+  static const int kNumberMaps_ = 6 + WindowsFrameInfo::STACK_INFO_LAST;
 
  private:
   friend class FastSourceLineResolver;
@@ -180,6 +238,10 @@ class FastSourceLineResolver::Module: public SourceLineResolverBase::Module {
   // this map, or the end of the range as given by the cfi_initial_rules_
   // entry (which FindCFIFrameInfo looks up first).
   StaticMap<MemAddr, char> cfi_delta_rules_;
+
+  // INLINE_ORIGIN records: used as a function name string pool for INLINE
+  // records.
+  StaticMap<int, char> inline_origins_;
 };
 
 }  // namespace google_breakpad
diff --git a/src/processor/fast_source_line_resolver_unittest.cc b/src/processor/fast_source_line_resolver_unittest.cc
index 5109e4f1..a8e22408 100644
--- a/src/processor/fast_source_line_resolver_unittest.cc
+++ b/src/processor/fast_source_line_resolver_unittest.cc
@@ -408,6 +408,108 @@ TEST_F(TestFastSourceLineResolver, TestLoadAndResolve) {
   ASSERT_EQ(frame.function_name, "Public2_2");
 }
 
+// Test adapted from basic_source_line_resolver_unittest.
+TEST_F(TestFastSourceLineResolver, TestLoadAndResolveOldInlines) {
+  TestCodeModule module("linux_inline");
+  ASSERT_TRUE(basic_resolver.LoadModule(
+      &module, testdata_dir +
+                   "/symbols/linux_inline/BBA6FA10B8AAB33D00000000000000000/"
+                   "linux_inline.old.sym"));
+  ASSERT_TRUE(basic_resolver.HasModule(&module));
+  // Convert module1 to fast_module:
+  ASSERT_TRUE(serializer.ConvertOneModule(module.code_file(), &basic_resolver,
+                                          &fast_resolver));
+  ASSERT_TRUE(fast_resolver.HasModule(&module));
+
+  StackFrame frame;
+  std::deque<std::unique_ptr<StackFrame>> inlined_frames;
+  frame.instruction = 0x161b6;
+  frame.module = &module;
+  fast_resolver.FillSourceLineInfo(&frame, &inlined_frames);
+
+  // main frame.
+  ASSERT_EQ(frame.function_name, "main");
+  ASSERT_EQ(frame.function_base, 0x15b30U);
+  ASSERT_EQ(frame.source_file_name, "linux_inline.cpp");
+  ASSERT_EQ(frame.source_line, 42);
+  ASSERT_EQ(frame.source_line_base, 0x161b6U);
+
+  ASSERT_EQ(inlined_frames.size(), 3UL);
+
+  // Inlined frames inside main frame.
+  ASSERT_EQ(inlined_frames[2]->function_name, "foo()");
+  ASSERT_EQ(inlined_frames[2]->function_base, 0x15b45U);
+  ASSERT_EQ(inlined_frames[2]->source_file_name, "linux_inline.cpp");
+  ASSERT_EQ(inlined_frames[2]->source_line, 39);
+  ASSERT_EQ(inlined_frames[2]->source_line_base, 0x161b6U);
+  ASSERT_EQ(inlined_frames[2]->trust, StackFrame::FRAME_TRUST_INLINE);
+
+  ASSERT_EQ(inlined_frames[1]->function_name, "bar()");
+  ASSERT_EQ(inlined_frames[1]->function_base, 0x15b72U);
+  ASSERT_EQ(inlined_frames[1]->source_file_name, "linux_inline.cpp");
+  ASSERT_EQ(inlined_frames[1]->source_line, 32);
+  ASSERT_EQ(inlined_frames[1]->source_line_base, 0x161b6U);
+  ASSERT_EQ(inlined_frames[1]->trust, StackFrame::FRAME_TRUST_INLINE);
+
+  ASSERT_EQ(inlined_frames[0]->function_name, "func()");
+  ASSERT_EQ(inlined_frames[0]->function_base, 0x15b83U);
+  ASSERT_EQ(inlined_frames[0]->source_file_name, "linux_inline.cpp");
+  ASSERT_EQ(inlined_frames[0]->source_line, 27);
+  ASSERT_EQ(inlined_frames[0]->source_line_base, 0x161b6U);
+  ASSERT_EQ(inlined_frames[0]->trust, StackFrame::FRAME_TRUST_INLINE);
+}
+
+// Test adapted from basic_source_line_resolver_unittest.
+TEST_F(TestFastSourceLineResolver, TestLoadAndResolveNewInlines) {
+  TestCodeModule module("linux_inline");
+  ASSERT_TRUE(basic_resolver.LoadModule(
+      &module, testdata_dir +
+                   "/symbols/linux_inline/BBA6FA10B8AAB33D00000000000000000/"
+                   "linux_inline.new.sym"));
+  ASSERT_TRUE(basic_resolver.HasModule(&module));
+  // Convert module1 to fast_module:
+  ASSERT_TRUE(serializer.ConvertOneModule(module.code_file(), &basic_resolver,
+                                          &fast_resolver));
+  ASSERT_TRUE(fast_resolver.HasModule(&module));
+
+  StackFrame frame;
+  std::deque<std::unique_ptr<StackFrame>> inlined_frames;
+  frame.instruction = 0x161b6;
+  frame.module = &module;
+  fast_resolver.FillSourceLineInfo(&frame, &inlined_frames);
+
+  // main frame.
+  ASSERT_EQ(frame.function_name, "main");
+  ASSERT_EQ(frame.function_base, 0x15b30U);
+  ASSERT_EQ(frame.source_file_name, "a.cpp");
+  ASSERT_EQ(frame.source_line, 42);
+  ASSERT_EQ(frame.source_line_base, 0x161b6U);
+
+  ASSERT_EQ(inlined_frames.size(), 3UL);
+
+  // Inlined frames inside main frame.
+  ASSERT_EQ(inlined_frames[2]->function_name, "foo()");
+  ASSERT_EQ(inlined_frames[2]->function_base, 0x15b45U);
+  ASSERT_EQ(inlined_frames[2]->source_file_name, "b.cpp");
+  ASSERT_EQ(inlined_frames[2]->source_line, 39);
+  ASSERT_EQ(inlined_frames[2]->source_line_base, 0x161b6U);
+  ASSERT_EQ(inlined_frames[2]->trust, StackFrame::FRAME_TRUST_INLINE);
+
+  ASSERT_EQ(inlined_frames[1]->function_name, "bar()");
+  ASSERT_EQ(inlined_frames[1]->function_base, 0x15b72U);
+  ASSERT_EQ(inlined_frames[1]->source_file_name, "c.cpp");
+  ASSERT_EQ(inlined_frames[1]->source_line, 32);
+  ASSERT_EQ(inlined_frames[1]->source_line_base, 0x161b6U);
+  ASSERT_EQ(inlined_frames[1]->trust, StackFrame::FRAME_TRUST_INLINE);
+
+  ASSERT_EQ(inlined_frames[0]->function_name, "func()");
+  ASSERT_EQ(inlined_frames[0]->function_base, 0x15b83U);
+  ASSERT_EQ(inlined_frames[0]->source_file_name, "linux_inline.cpp");
+  ASSERT_EQ(inlined_frames[0]->source_line, 27);
+  ASSERT_EQ(inlined_frames[0]->source_line_base, 0x161b6U);
+  ASSERT_EQ(inlined_frames[0]->trust, StackFrame::FRAME_TRUST_INLINE);
+}
+
 TEST_F(TestFastSourceLineResolver, TestInvalidLoads) {
   TestCodeModule module3("module3");
   ASSERT_TRUE(basic_resolver.LoadModule(&module3,
diff --git a/src/processor/module_serializer.cc b/src/processor/module_serializer.cc
index 04cadc80..8ad0d589 100644
--- a/src/processor/module_serializer.cc
+++ b/src/processor/module_serializer.cc
@@ -43,10 +43,15 @@
 
 namespace google_breakpad {
 
-// Definition of static member variable in SimplerSerializer<Funcion>, which
-// is declared in file "simple_serializer-inl.h"
-RangeMapSerializer< MemAddr, linked_ptr<BasicSourceLineResolver::Line> >
-SimpleSerializer<BasicSourceLineResolver::Function>::range_map_serializer_;
+// Definition of static member variables in SimplerSerializer<Funcion> and
+// SimplerSerializer<Inline>, which are declared in file
+// "simple_serializer-inl.h"
+RangeMapSerializer<MemAddr, linked_ptr<BasicSourceLineResolver::Line>>
+    SimpleSerializer<BasicSourceLineResolver::Function>::range_map_serializer_;
+ContainedRangeMapSerializer<MemAddr,
+                            linked_ptr<BasicSourceLineResolver::Inline>>
+    SimpleSerializer<
+        BasicSourceLineResolver::Function>::inline_range_map_serializer_;
 
 size_t ModuleSerializer::SizeOf(const BasicSourceLineResolver::Module& module) {
   size_t total_size_alloc_ = 0;
@@ -66,6 +71,8 @@ size_t ModuleSerializer::SizeOf(const BasicSourceLineResolver::Module& module) {
      module.cfi_initial_rules_);
   map_sizes_[map_index++] = cfi_delta_rules_serializer_.SizeOf(
      module.cfi_delta_rules_);
+  map_sizes_[map_index++] =
+      inline_origin_serializer_.SizeOf(module.inline_origins_);
 
   // Header size.
   total_size_alloc_ += kNumberMaps_ * sizeof(uint32_t);
@@ -95,6 +102,7 @@ char* ModuleSerializer::Write(const BasicSourceLineResolver::Module& module,
     dest = wfi_serializer_.Write(&(module.windows_frame_info_[i]), dest);
   dest = cfi_init_rules_serializer_.Write(module.cfi_initial_rules_, dest);
   dest = cfi_delta_rules_serializer_.Write(module.cfi_delta_rules_, dest);
+  dest = inline_origin_serializer_.Write(module.inline_origins_, dest);
   // Write a null terminator.
   dest = SimpleSerializer<char>::Write(0, dest);
   return dest;
diff --git a/src/processor/module_serializer.h b/src/processor/module_serializer.h
index 932ac3d7..94e25c01 100644
--- a/src/processor/module_serializer.h
+++ b/src/processor/module_serializer.h
@@ -99,6 +99,7 @@ class ModuleSerializer {
   typedef BasicSourceLineResolver::Line Line;
   typedef BasicSourceLineResolver::Function Function;
   typedef BasicSourceLineResolver::PublicSymbol PublicSymbol;
+  typedef BasicSourceLineResolver::InlineOrigin InlineOrigin;
 
   // Internal implementation for ConvertOneModule and ConvertAllModules methods.
   bool SerializeModuleAndLoadIntoFastResolver(
@@ -120,6 +121,7 @@ class ModuleSerializer {
                               linked_ptr<WindowsFrameInfo> > wfi_serializer_;
   RangeMapSerializer<MemAddr, string> cfi_init_rules_serializer_;
   StdMapSerializer<MemAddr, string> cfi_delta_rules_serializer_;
+  StdMapSerializer<int, linked_ptr<InlineOrigin>> inline_origin_serializer_;
 };
 
 }  // namespace google_breakpad
diff --git a/src/processor/simple_serializer-inl.h b/src/processor/simple_serializer-inl.h
index cb1a0408..4b4200e4 100644
--- a/src/processor/simple_serializer-inl.h
+++ b/src/processor/simple_serializer-inl.h
@@ -113,6 +113,25 @@ class SimpleSerializer<BasicSourceLineResolver::Line> {
   }
 };
 
+// Specializations of SimpleSerializer: InlineOrigin
+template <>
+class SimpleSerializer<BasicSourceLineResolver::InlineOrigin> {
+  typedef BasicSourceLineResolver::InlineOrigin InlineOrigin;
+
+ public:
+  static size_t SizeOf(const InlineOrigin& origin) {
+    return SimpleSerializer<bool>::SizeOf(origin.has_file_id) +
+           SimpleSerializer<int32_t>::SizeOf(origin.source_file_id) +
+           SimpleSerializer<string>::SizeOf(origin.name);
+  }
+  static char* Write(const InlineOrigin& origin, char* dest) {
+    dest = SimpleSerializer<bool>::Write(origin.has_file_id, dest);
+    dest = SimpleSerializer<int32_t>::Write(origin.source_file_id, dest);
+    dest = SimpleSerializer<string>::Write(origin.name, dest);
+    return dest;
+  }
+};
+
 // Specializations of SimpleSerializer: PublicSymbol
 template<>
 class SimpleSerializer<BasicSourceLineResolver::PublicSymbol> {
@@ -165,7 +184,7 @@ class SimpleSerializer<WindowsFrameInfo> {
 };
 
 // Specializations of SimpleSerializer: Linked_ptr version of
-// Line, Function, PublicSymbol, WindowsFrameInfo.
+// Line, InlineOrigin, Inline, Function, PublicSymbol, WindowsFrameInfo.
 template<>
 class SimpleSerializer< linked_ptr<BasicSourceLineResolver::Line> > {
   typedef BasicSourceLineResolver::Line Line;
@@ -181,11 +200,86 @@ class SimpleSerializer< linked_ptr<BasicSourceLineResolver::Line> > {
   }
 };
 
+template <>
+class SimpleSerializer<linked_ptr<BasicSourceLineResolver::InlineOrigin>> {
+  typedef BasicSourceLineResolver::InlineOrigin InlineOrigin;
+
+ public:
+  static size_t SizeOf(const linked_ptr<InlineOrigin>& origin_ptr) {
+    if (origin_ptr.get() == NULL)
+      return 0;
+    return SimpleSerializer<InlineOrigin>::SizeOf(*(origin_ptr.get()));
+  }
+  static char* Write(const linked_ptr<InlineOrigin>& origin_ptr, char* dest) {
+    if (origin_ptr.get())
+      dest = SimpleSerializer<InlineOrigin>::Write(*(origin_ptr.get()), dest);
+    return dest;
+  }
+};
+
+// Specializations of SimpleSerializer: Inline
+template <>
+class SimpleSerializer<linked_ptr<BasicSourceLineResolver::Inline>>;
+template <>
+class SimpleSerializer<BasicSourceLineResolver::Inline> {
+  typedef BasicSourceLineResolver::Inline Inline;
+
+ public:
+  inline static size_t SizeOf(const Inline& in);
+  inline static char* Write(const Inline& in, char* dest);
+};
+
+template <>
+class SimpleSerializer<linked_ptr<BasicSourceLineResolver::Inline>> {
+  typedef BasicSourceLineResolver::Inline Inline;
+
+ public:
+  static size_t SizeOf(const linked_ptr<Inline>& inline_ptr) {
+    if (inline_ptr.get() == NULL)
+      return 0;
+    return SimpleSerializer<Inline>::SizeOf(*(inline_ptr.get()));
+  }
+  static char* Write(const linked_ptr<Inline>& inline_ptr, char* dest) {
+    if (inline_ptr.get())
+      dest = SimpleSerializer<Inline>::Write(*(inline_ptr.get()), dest);
+    return dest;
+  }
+};
+
+size_t SimpleSerializer<BasicSourceLineResolver::Inline>::SizeOf(
+    const Inline& in) {
+  return SimpleSerializer<bool>::SizeOf(in.has_call_site_file_id) +
+         SimpleSerializer<int32_t>::SizeOf(in.inline_nest_level) +
+         SimpleSerializer<int32_t>::SizeOf(in.call_site_line) +
+         SimpleSerializer<int32_t>::SizeOf(in.call_site_file_id) +
+         SimpleSerializer<int32_t>::SizeOf(in.origin_id) +
+         sizeof(uint32_t) +  // This is to store the size of inline_ranges.
+         (in.inline_ranges.size() * sizeof(MemAddr) * 2);
+}
+
+char* SimpleSerializer<BasicSourceLineResolver::Inline>::Write(const Inline& in,
+                                                               char* dest) {
+  dest = SimpleSerializer<bool>::Write(in.has_call_site_file_id, dest);
+  dest = SimpleSerializer<int32_t>::Write(in.inline_nest_level, dest);
+  dest = SimpleSerializer<int32_t>::Write(in.call_site_line, dest);
+  dest = SimpleSerializer<int32_t>::Write(in.call_site_file_id, dest);
+  dest = SimpleSerializer<int32_t>::Write(in.origin_id, dest);
+  // Write the size of inline_ranges.
+  dest = SimpleSerializer<int32_t>::Write(in.inline_ranges.size(), dest);
+  for (const std::pair<MemAddr, MemAddr>& range : in.inline_ranges) {
+    dest = SimpleSerializer<MemAddr>::Write(range.first, dest);
+    dest = SimpleSerializer<MemAddr>::Write(range.second, dest);
+  }
+  return dest;
+}
+
 template<>
 class SimpleSerializer<BasicSourceLineResolver::Function> {
   // Convenient type names.
   typedef BasicSourceLineResolver::Function Function;
   typedef BasicSourceLineResolver::Line Line;
+  typedef BasicSourceLineResolver::Inline Inline;
+
  public:
   static size_t SizeOf(const Function& func) {
     unsigned int size = 0;
@@ -193,6 +287,11 @@ class SimpleSerializer<BasicSourceLineResolver::Function> {
     size += SimpleSerializer<MemAddr>::SizeOf(func.address);
     size += SimpleSerializer<MemAddr>::SizeOf(func.size);
     size += SimpleSerializer<int32_t>::SizeOf(func.parameter_size);
+    size += SimpleSerializer<bool>::SizeOf(func.is_multiple);
+    // This extra size is used to store the size of serialized func.inlines, so
+    // we know where to start de-serialize func.lines.
+    size += sizeof(int32_t);
+    size += inline_range_map_serializer_.SizeOf(&func.inlines);
     size += range_map_serializer_.SizeOf(func.lines);
     return size;
   }
@@ -202,12 +301,22 @@ class SimpleSerializer<BasicSourceLineResolver::Function> {
     dest = SimpleSerializer<MemAddr>::Write(func.address, dest);
     dest = SimpleSerializer<MemAddr>::Write(func.size, dest);
     dest = SimpleSerializer<int32_t>::Write(func.parameter_size, dest);
+    dest = SimpleSerializer<bool>::Write(func.is_multiple, dest);
+    char* old_dest = dest;
+    dest += sizeof(int32_t);
+    dest = inline_range_map_serializer_.Write(&func.inlines, dest);
+    // Write the size of serialized func.inlines. The size doesn't include size
+    // field itself.
+    SimpleSerializer<MemAddr>::Write(dest - old_dest - sizeof(int32_t),
+                                     old_dest);
     dest = range_map_serializer_.Write(func.lines, dest);
     return dest;
   }
  private:
   // This static member is defined in module_serializer.cc.
-  static RangeMapSerializer< MemAddr, linked_ptr<Line> > range_map_serializer_;
+  static RangeMapSerializer<MemAddr, linked_ptr<Line>> range_map_serializer_;
+  static ContainedRangeMapSerializer<MemAddr, linked_ptr<Inline>>
+      inline_range_map_serializer_;
 };
 
 template<>
diff --git a/src/processor/source_line_resolver_base_types.h b/src/processor/source_line_resolver_base_types.h
index 4d3ce066..82889550 100644
--- a/src/processor/source_line_resolver_base_types.h
+++ b/src/processor/source_line_resolver_base_types.h
@@ -71,6 +71,7 @@ class SourceLineResolverBase::AutoFileCloser {
 };
 
 struct SourceLineResolverBase::InlineOrigin {
+  InlineOrigin() {}
   InlineOrigin(bool has_file_id, int32_t source_file_id, const string& name)
       : has_file_id(has_file_id),
         source_file_id(source_file_id),
@@ -84,6 +85,7 @@ struct SourceLineResolverBase::InlineOrigin {
 struct SourceLineResolverBase::Inline {
   // A vector of (address, size) pair for a INLINE record.
   using InlineRanges = std::vector<std::pair<MemAddr, MemAddr>>;
+  Inline() {}
   Inline(bool has_call_site_file_id,
          int32_t inline_nest_level,
          int32_t call_site_line,