Browse Source

binman: Allow writing a map file when something goes wrong

When we get a problem like overlapping regions it is sometimes hard to
figure what what is going on. At present we don't write the map file in
this case. However the file does provide useful information.

Catch any packing errors and write a map file (if enabled with -m) to aid
debugging.

Signed-off-by: Simon Glass <sjg@chromium.org>
Simon Glass 6 years ago
parent
commit
163ed6c342
4 changed files with 46 additions and 8 deletions
  1. 9 3
      tools/binman/control.py
  2. 9 2
      tools/binman/entry.py
  3. 22 2
      tools/binman/ftest.py
  4. 6 1
      tools/binman/image.py

+ 9 - 3
tools/binman/control.py

@@ -163,9 +163,15 @@ def Binman(options, args):
                 # completed and written, but that does not seem important.
                 # completed and written, but that does not seem important.
                 image.GetEntryContents()
                 image.GetEntryContents()
                 image.GetEntryOffsets()
                 image.GetEntryOffsets()
-                image.PackEntries()
-                image.CheckSize()
-                image.CheckEntries()
+                try:
+                    image.PackEntries()
+                    image.CheckSize()
+                    image.CheckEntries()
+                except Exception as e:
+                    if options.map:
+                        fname = image.WriteMap()
+                        print "Wrote map file '%s' to show errors"  % fname
+                    raise
                 image.SetImagePos()
                 image.SetImagePos()
                 if options.update_fdt:
                 if options.update_fdt:
                     image.SetCalculatedProperties()
                     image.SetCalculatedProperties()

+ 9 - 2
tools/binman/entry.py

@@ -390,10 +390,17 @@ class Entry(object):
         """
         """
         pass
         pass
 
 
+    @staticmethod
+    def GetStr(value):
+        if value is None:
+            return '<none>  '
+        return '%08x' % value
+
     @staticmethod
     @staticmethod
     def WriteMapLine(fd, indent, name, offset, size, image_pos):
     def WriteMapLine(fd, indent, name, offset, size, image_pos):
-        print('%08x  %s%08x  %08x  %s' % (image_pos, ' ' * indent, offset,
-                                          size, name), file=fd)
+        print('%s  %s%s  %s  %s' % (Entry.GetStr(image_pos), ' ' * indent,
+                                    Entry.GetStr(offset), Entry.GetStr(size),
+                                    name), file=fd)
 
 
     def WriteMap(self, fd, indent):
     def WriteMap(self, fd, indent):
         """Write a map of the entry to a .map file
         """Write a map of the entry to a .map file

+ 22 - 2
tools/binman/ftest.py

@@ -1607,8 +1607,9 @@ class TestFunctional(unittest.TestCase):
 
 
     def testExpandSizeBad(self):
     def testExpandSizeBad(self):
         """Test an expanding entry which fails to provide contents"""
         """Test an expanding entry which fails to provide contents"""
-        with self.assertRaises(ValueError) as e:
-            self._DoReadFileDtb('89_expand_size_bad.dts', map=True)
+        with test_util.capture_sys_output() as (stdout, stderr):
+            with self.assertRaises(ValueError) as e:
+                self._DoReadFileDtb('89_expand_size_bad.dts', map=True)
         self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
         self.assertIn("Node '/binman/_testing': Cannot obtain contents when "
                       'expanding entry', str(e.exception))
                       'expanding entry', str(e.exception))
 
 
@@ -1724,6 +1725,25 @@ class TestFunctional(unittest.TestCase):
             TestFunctional._MakeInputFile('-boot', fd.read())
             TestFunctional._MakeInputFile('-boot', fd.read())
         data = self._DoReadFile('97_elf_strip.dts')
         data = self._DoReadFile('97_elf_strip.dts')
 
 
+    def testPackOverlapMap(self):
+        """Test that overlapping regions are detected"""
+        with test_util.capture_sys_output() as (stdout, stderr):
+            with self.assertRaises(ValueError) as e:
+                self._DoTestFile('14_pack_overlap.dts', map=True)
+        map_fname = tools.GetOutputFilename('image.map')
+        self.assertEqual("Wrote map file '%s' to show errors\n" % map_fname,
+                         stdout.getvalue())
+
+        # We should not get an inmage, but there should be a map file
+        self.assertFalse(os.path.exists(tools.GetOutputFilename('image.bin')))
+        self.assertTrue(os.path.exists(map_fname))
+        map_data = tools.ReadFile(map_fname)
+        self.assertEqual('''ImagePos    Offset      Size  Name
+<none>    00000000  00000007  main-section
+<none>     00000000  00000004  u-boot
+<none>     00000003  00000004  u-boot-align
+''', map_data)
+
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
     unittest.main()
     unittest.main()

+ 6 - 1
tools/binman/image.py

@@ -139,10 +139,15 @@ class Image:
         return self._section.GetEntries()
         return self._section.GetEntries()
 
 
     def WriteMap(self):
     def WriteMap(self):
-        """Write a map of the image to a .map file"""
+        """Write a map of the image to a .map file
+
+        Returns:
+            Filename of map file written
+        """
         filename = '%s.map' % self._name
         filename = '%s.map' % self._name
         fname = tools.GetOutputFilename(filename)
         fname = tools.GetOutputFilename(filename)
         with open(fname, 'w') as fd:
         with open(fname, 'w') as fd:
             print('%8s  %8s  %8s  %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
             print('%8s  %8s  %8s  %s' % ('ImagePos', 'Offset', 'Size', 'Name'),
                   file=fd)
                   file=fd)
             self._section.WriteMap(fd, 0)
             self._section.WriteMap(fd, 0)
+        return fname