summaryrefslogtreecommitdiffstats
path: root/meta/classes/package.bbclass
diff options
context:
space:
mode:
authorMark Hatle <mark.hatle@windriver.com>2011-02-09 21:22:42 -0600
committerRichard Purdie <richard.purdie@linuxfoundation.org>2011-02-25 22:43:33 +0000
commit40ea19d6e1c4074df4793e348ed25338477aeebb (patch)
treeb362443c3914a38aceca3fe0238e9f1cf78dcd31 /meta/classes/package.bbclass
parent16102e18902e56bf76d256cebb890743a05d021b (diff)
downloadpoky-40ea19d6e1c4074df4793e348ed25338477aeebb.tar.gz
package.bbclass: Refactor split and strip function
Refactor the function to eliminate additional interations/walks of the filesystem.. Elimiate multiple runs of the external 'file' command as well. Signed-off-by: Mark Hatle <mark.hatle@windriver.com>
Diffstat (limited to 'meta/classes/package.bbclass')
-rw-r--r--meta/classes/package.bbclass242
1 files changed, 144 insertions, 98 deletions
diff --git a/meta/classes/package.bbclass b/meta/classes/package.bbclass
index 86e24bc1fa..59a0601d0d 100644
--- a/meta/classes/package.bbclass
+++ b/meta/classes/package.bbclass
@@ -184,7 +184,7 @@ def splitfile(file, debugfile, debugsrcdir, d):
184 184
185 # We ignore kernel modules, we don't generate debug info files. 185 # We ignore kernel modules, we don't generate debug info files.
186 if file.find("/lib/modules/") != -1 and file.endswith(".ko"): 186 if file.find("/lib/modules/") != -1 and file.endswith(".ko"):
187 return 0 187 return 1
188 188
189 newmode = None 189 newmode = None
190 if not os.access(file, os.W_OK) or os.access(file, os.R_OK): 190 if not os.access(file, os.W_OK) or os.access(file, os.R_OK):
@@ -239,9 +239,14 @@ def splitfile2(debugsrcdir, d):
239 #bb.note("rmdir -p %s" % dir) 239 #bb.note("rmdir -p %s" % dir)
240 os.system("rmdir -p %s 2>/dev/null" % dir) 240 os.system("rmdir -p %s 2>/dev/null" % dir)
241 241
242def runstrip(file, d): 242def runstrip(file, elftype, d):
243 # Function to strip a single file, called from split_and_strip_files below 243 # Function to strip a single file, called from split_and_strip_files below
244 # A working 'file' (one which works on the target architecture) 244 # A working 'file' (one which works on the target architecture)
245 #
246 # The elftype is a bit pattern (explained in split_and_strip_files) to tell
247 # us what type of file we're processing...
248 # 4 - executable
249 # 8 - shared library
245 250
246 import commands, stat 251 import commands, stat
247 252
@@ -258,16 +263,12 @@ def runstrip(file, d):
258 newmode = origmode | stat.S_IWRITE | stat.S_IREAD 263 newmode = origmode | stat.S_IWRITE | stat.S_IREAD
259 os.chmod(file, newmode) 264 os.chmod(file, newmode)
260 265
261 ret, result = commands.getstatusoutput("%sfile '%s'" % (pathprefix, file))
262
263 if ret:
264 bb.error("runstrip: 'file %s' failed" % file)
265 return 0
266
267 extraflags = "" 266 extraflags = ""
268 if ".so" in file and "shared" in result: 267 # .so and shared library
268 if ".so" in file and elftype & 8:
269 extraflags = "--remove-section=.comment --remove-section=.note --strip-unneeded" 269 extraflags = "--remove-section=.comment --remove-section=.note --strip-unneeded"
270 elif "shared" in result or "executable" in result: 270 # shared or executable:
271 elif elftype & 8 or elftype & 4:
271 extraflags = "--remove-section=.comment --remove-section=.note" 272 extraflags = "--remove-section=.comment --remove-section=.note"
272 273
273 stripcmd = "'%s' %s '%s'" % (strip, extraflags, file) 274 stripcmd = "'%s' %s '%s'" % (strip, extraflags, file)
@@ -410,109 +411,158 @@ python split_and_strip_files () {
410 411
411 os.chdir(dvar) 412 os.chdir(dvar)
412 413
413 def isexec(path): 414 # Return type (bits):
414 try: 415 # 0 - not elf
415 s = os.stat(path) 416 # 1 - ELF
416 except (os.error, AttributeError): 417 # 2 - stripped
417 return 0 418 # 4 - executable
418 return ((s[stat.ST_MODE] & stat.S_IXUSR) or (s[stat.ST_MODE] & stat.S_IXGRP) or (s[stat.ST_MODE] & stat.S_IXOTH)) 419 # 8 - shared library
419
420 # Return 0 - not elf, 1 - ELF & not stripped, 2 - ELF & stripped
421 def isELF(path): 420 def isELF(path):
421 type = 0
422 pathprefix = "export PATH=%s; " % bb.data.getVar('PATH', d, True) 422 pathprefix = "export PATH=%s; " % bb.data.getVar('PATH', d, True)
423 ret, result = commands.getstatusoutput("%sfile '%s'" % (pathprefix, path)) 423 ret, result = commands.getstatusoutput("%sfile '%s'" % (pathprefix, path))
424 424
425 if ret: 425 if ret:
426 bb.error("split_and_strip_files: 'file %s' failed" % path) 426 bb.error("split_and_strip_files: 'file %s' failed" % path)
427 return 0 427 return type
428 428
429 # Not stripped 429 # Not stripped
430 if "ELF" in result and "not stripped" in result:
431 return 1
432
433 # Stripped
434 if "ELF" in result: 430 if "ELF" in result:
435 return 2 431 type |= 1
432 if "not stripped" not in result:
433 type |= 2
434 if "executable" in result:
435 type |= 4
436 if "shared" in result:
437 type |= 8
438 return type
436 439
437 return 0;
438 440
439 # 441 #
440 # First lets process debug splitting 442 # First lets figure out all of the files we may have to process ... do this only once!
441 # 443 #
442 if (bb.data.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT', d, True) != '1'): 444 file_list = {}
443 file_links = {} 445 file_links = {}
444 446 if (bb.data.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT', d, True) != '1') and \
447 (bb.data.getVar('INHIBIT_PACKAGE_STRIP', d, True) != '1'):
445 for root, dirs, files in os.walk(dvar): 448 for root, dirs, files in os.walk(dvar):
446 for f in files: 449 for f in files:
447 file = os.path.join(root, f) 450 file = os.path.join(root, f)
448 # Skip debug files, it must be executable, and must be a file (or link) 451 # Only process files (and symlinks)... Skip files that are obviously debug files
449 if not (debugappend != "" and file.endswith(debugappend)) and not (debugdir != "" and debugdir in os.path.dirname(file[len(dvar):])) and isexec(file) and os.path.isfile(file): 452 if not (debugappend != "" and file.endswith(debugappend)) and \
450 src = file[len(dvar):] 453 not (debugdir != "" and debugdir in os.path.dirname(file[len(dvar):])) and \
451 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend 454 os.path.isfile(file):
452 fpath = dvar + dest 455 try:
453 # Preserve symlinks in debug area...
454 if os.path.islink(file):
455 target = os.readlink(file)
456 if not os.path.isabs(target):
457 target = os.path.join(os.path.dirname(file), target)
458 if isELF(target):
459 ltarget = os.readlink(file)
460 lpath = os.path.dirname(ltarget)
461 lbase = os.path.basename(ltarget)
462 ftarget = ""
463 if lpath and lpath != ".":
464 ftarget += lpath + debugdir + "/"
465 ftarget += lbase + debugappend
466 bb.mkdirhier(os.path.dirname(fpath))
467 #bb.note("Symlink %s -> %s" % (fpath, ftarget))
468 os.symlink(ftarget, fpath)
469 continue
470
471 # If the file is elf we need to check it for hard links
472 elf_file = isELF(file)
473 if elf_file:
474 # Preserve hard links in debug area...
475 s = os.stat(file) 456 s = os.stat(file)
476 if s.st_nlink > 1: 457 except OSError, (err, strerror):
477 file_reference = "%d_%d" % (s.st_dev, s.st_ino) 458 if err != errno.ENOENT:
478 if file_reference not in file_links: 459 raise
479 # If this is new, and already stripped we avoid recording it 460 # Skip broken symlinks
480 # as we'll be unable to set the hard link later, because it 461 continue
481 # won't be split/stripped... 462 # Is the item excutable? Then we need to process it.
482 if elf_file != 2: 463 if (s[stat.ST_MODE] & stat.S_IXUSR) or \
483 file_links[file_reference] = fpath 464 (s[stat.ST_MODE] & stat.S_IXGRP) or \
465 (s[stat.ST_MODE] & stat.S_IXOTH):
466 # If it's a symlink, and points to an ELF file, we capture the readlink target
467 if os.path.islink(file):
468 target = os.readlink(file)
469 if not os.path.isabs(target):
470 ltarget = os.path.join(os.path.dirname(file), target)
484 else: 471 else:
485 bb.mkdirhier(os.path.dirname(fpath)) 472 ltarget = target
486 #bb.note("Link %s -> %s" % (fpath, file_links[file_reference]))
487 os.link(file_links[file_reference], fpath)
488 continue
489 473
490 if elf_file == 2: 474 if isELF(ltarget):
491 bb.warn("File '%s' was already stripped, this will prevent future debugging!" % (src)) 475 #bb.note("Sym: %s (%d)" % (ltarget, isELF(ltarget)))
476 file_list[file] = "sym: " + target
492 continue 477 continue
478 # It's a file (or hardlink), not a link
479 # ...but is it ELF, and is it already stripped?
480 elf_file = isELF(file)
481 if elf_file & 1:
482 # Check if it's a hard link to something else
483 if s.st_nlink > 1:
484 file_reference = "%d_%d" % (s.st_dev, s.st_ino)
485 # Hard link to something else
486 file_list[file] = "hard: " + file_reference
487 continue
493 488
494 # Split and Strip 489 file_list[file] = "ELF: %d" % elf_file
495 bb.mkdirhier(os.path.dirname(fpath))
496 #bb.note("Split %s -> %s" % (file, fpath))
497 splitfile(file, fpath, debugsrcdir, d)
498 490
499 # Process the debugsrcdir if requested...
500 splitfile2(debugsrcdir, d)
501 491
502 # The above may have generated dangling symlinks 492 #
503 for root, dirs, files in os.walk(dvar): 493 # First lets process debug splitting
504 for f in files: 494 #
505 file = os.path.join(root, f) 495 if (bb.data.getVar('INHIBIT_PACKAGE_DEBUG_SPLIT', d, True) != '1'):
506 # We ONLY strip dangling links if they're debug generated! 496 for file in file_list:
507 if (debugappend != "" and file.endswith(debugappend)) or (debugdir != "" and debugdir in os.path.dirname(file[len(dvar):])): 497 src = file[len(dvar):]
508 try: 498 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
509 s = os.stat(file) 499 fpath = dvar + dest
510 except OSError, (err, strerror): 500 # Preserve symlinks in debug area...
511 if err != errno.ENOENT: 501 if file_list[file].startswith("sym: "):
512 raise 502 ltarget = file_list[file][5:]
513 #bb.note("Remove dangling link %s" % file) 503 lpath = os.path.dirname(ltarget)
514 os.unlink(file) 504 lbase = os.path.basename(ltarget)
505 ftarget = ""
506 if lpath and lpath != ".":
507 ftarget += lpath + debugdir + "/"
508 ftarget += lbase + debugappend
509 bb.mkdirhier(os.path.dirname(fpath))
510 #bb.note("Symlink %s -> %s" % (fpath, ftarget))
511 os.symlink(ftarget, fpath)
512 continue
513
514 # Preserve hard links in debug area...
515 file_reference = ""
516 if file_list[file].startswith("hard: "):
517 file_reference = file_list[file][6:]
518 if file_reference not in file_links:
519 # If this is a new file, add it as a reference, and
520 # update it's type, so we can fall through and split
521 file_list[file] = "ELF: %d" % (isELF(file))
522 else:
523 target = file_links[file_reference][len(dvar):]
524 ftarget = dvar + debuglibdir + os.path.dirname(target) + debugdir + "/" + os.path.basename(target) + debugappend
525 bb.mkdirhier(os.path.dirname(fpath))
526 #bb.note("Link %s -> %s" % (fpath, ftarget))
527 os.link(ftarget, fpath)
528 continue
515 529
530 # It's ELF...
531 if file_list[file].startswith("ELF: "):
532 elf_file = int(file_list[file][5:])
533 if elf_file & 2:
534 bb.warn("File '%s' was already stripped, this will prevent future debugging!" % (src))
535 continue
536
537 # Split the file...
538 bb.mkdirhier(os.path.dirname(fpath))
539 #bb.note("Split %s -> %s" % (file, fpath))
540 # Only store off the hard link reference if we successfully split!
541 if splitfile(file, fpath, debugsrcdir, d) == 0 and file_reference != "":
542 file_links[file_reference] = file
543
544 # The above may have generated dangling symlinks, remove them!
545 # Dangling symlinks are a result of something NOT being split, such as a stripped binary.
546 # This should be a rare occurance, but we want to clean up anyway.
547 for file in file_list:
548 if file_list[file].startswith("sym: "):
549 src = file[len(dvar):]
550 dest = debuglibdir + os.path.dirname(src) + debugdir + "/" + os.path.basename(src) + debugappend
551 fpath = dvar + dest
552 try:
553 s = os.stat(fpath)
554 except OSError, (err, strerror):
555 if err != errno.ENOENT:
556 raise
557 #bb.note("Remove dangling link %s -> %s" % (fpath, os.readlink(fpath)))
558 os.unlink(fpath)
559 # This could leave an empty debug directory laying around
560 # take care of the obvious case...
561 os.system("rmdir %s 2>/dev/null" % os.path.dirname(fpath))
562
563 # Process the debugsrcdir if requested...
564 # This copies and places the referenced sources for later debugging...
565 splitfile2(debugsrcdir, d)
516 # 566 #
517 # End of debug splitting 567 # End of debug splitting
518 # 568 #
@@ -521,15 +571,11 @@ python split_and_strip_files () {
521 # Now lets go back over things and strip them 571 # Now lets go back over things and strip them
522 # 572 #
523 if (bb.data.getVar('INHIBIT_PACKAGE_STRIP', d, True) != '1'): 573 if (bb.data.getVar('INHIBIT_PACKAGE_STRIP', d, True) != '1'):
524 for root, dirs, files in os.walk(dvar): 574 for file in file_list:
525 for f in files: 575 if file_list[file].startswith("ELF: "):
526 file = os.path.join(root, f) 576 elf_file = int(file_list[file][5:])
527 # if not a debugfile, is executable, is a file, and not a symlink 577 #bb.note("Strip %s" % file)
528 if not (debugappend != "" and file.endswith(debugappend)) and not (debugdir != "" and debugdir in os.path.dirname(file[len(dvar):])) and isexec(file) and os.path.isfile(file) and not os.path.islink(file): 578 runstrip(file, elf_file, d)
529 elf_file = isELF(file)
530 if elf_file and elf_file != 2:
531 #bb.note("Strip %s" % file)
532 runstrip(file, d)
533 # 579 #
534 # End of strip 580 # End of strip
535 # 581 #