6 คะแนน โดย GN⁺ 2024-02-03 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

ไฟล์ปฏิบัติการแบบไบนารีประกอบขึ้นอย่างไร? มาสำรวจกัน!

  • ไฟล์ปฏิบัติการไม่ใช่สิ่งที่เข้าใจไม่ได้ แต่เป็นรูปแบบไฟล์มาตรฐานชนิดหนึ่ง
  • บทความนี้ว่าด้วยการจัดการไบนารี ELF บนลินุกซ์ โดยใช้ภาษา C แต่ก็ประยุกต์กับภาษาแบบคอมไพล์อื่น ๆ ได้เช่นกัน
  • เรียนรู้เกี่ยวกับ สัญลักษณ์ (symbol), เซกชัน (section) และ เซกเมนต์ (segment)
  • สัญลักษณ์เปรียบได้กับชื่อฟังก์ชัน ถูกจัดอยู่ในเซกชัน และเซกชันต่าง ๆ ก็ถูกรวมเป็นเซกเมนต์
  • ใช้เครื่องมือ readelf เพื่อสำรวจสิ่งเหล่านี้

ขั้นที่ 1: เปิดด้วยโปรแกรมแก้ไขข้อความ!

  • เป็นวิธีที่ง่ายที่สุดในการดูไบนารี และจะเห็นข้อความอย่าง "Penguin!" และ "ELF"

ขั้นที่ 2: ใช้ readelf เพื่อดูตารางสัญลักษณ์

  • ใช้ readelf --symbols เพื่อดูสัญลักษณ์ได้
  • สามารถเห็นสัญลักษณ์อย่าง main, puts, _start
  • โปรแกรมไม่ได้เริ่มที่ main แต่เริ่มที่ _start

สัญลักษณ์

  • เมื่อเขียนโปรแกรม จะมีการสร้างสัญลักษณ์สำหรับฟังก์ชันต่าง ๆ
  • เมื่อต้องเรียกใช้ฟังก์ชันจากไลบรารี ก็จำเป็นต้องมีสัญลักษณ์เพื่อค้นหาโค้ดของฟังก์ชันนั้น
  • การลิงก์เกิดขึ้นได้ทั้งแบบสแตติก (static linking) และไดนามิก (dynamic linking)

ขั้นที่ 3: ใช้ objdump เพื่อดูไบนารีและเรียนรู้เรื่องเซกชัน!

  • objdump ให้วิธีที่ดีกว่าในการดูไบนารี
  • สามารถดูเซกชันอย่าง .text, .rodata, .interp ได้
  • เซกชันใช้ในช่วงลิงก์ ส่วนเซกเมนต์ใช้ในช่วงรันไทม์

ขั้นที่ 4: ดูแอสเซมบลี!

  • เซกชัน .text มีโค้ดแอสเซมบลีอยู่
  • ใช้ objdump -d เพื่อดูโค้ดแอสเซมบลี

ขั้นที่ 5: ดูเซกเมนต์!

  • โปรแกรมประกอบด้วยเซกเมนต์ หรือ program header
  • ใช้ readelf --segments เพื่อดูเซกเมนต์
  • เซกเมนต์เป็นตัวกำหนดว่าจะแยกส่วนต่าง ๆ ของโปรแกรมในหน่วยความจำอย่างไร

ไม่ใช่เวทมนตร์!

  • ไฟล์ปฏิบัติการไม่ใช่เวทมนตร์ และ ELF ก็เหมือนกับรูปแบบไฟล์อื่น ๆ
  • สามารถใช้ readelf, nm, objdump เพื่อตรวจสอบไบนารีบนลินุกซ์ได้

ความคิดเห็นของ GN⁺

  • บทความนี้มีประโยชน์มากสำหรับวิศวกรซอฟต์แวร์ระดับเริ่มต้นที่ต้องการเข้าใจโครงสร้างของไฟล์ปฏิบัติการแบบไบนารี
  • ให้ข้อมูลเชิงปฏิบัติเกี่ยวกับแนวคิดของสัญลักษณ์ เซกชัน เซกเมนต์ และเครื่องมือสำหรับตรวจสอบสิ่งเหล่านี้ (readelf, objdump)
  • ยังช่วยปูพื้นความเข้าใจว่าจริง ๆ แล้วโปรแกรมถูกโหลดเข้าหน่วยความจำและทำงานอย่างไร ซึ่งอาจจุดประกายความสนใจในด้าน system programming ได้

1 ความคิดเห็น

 
GN⁺ 2024-02-03
ความเห็นจาก Hacker News
  • ผู้ใช้คนหนึ่งแนะนำให้ลองเขียน ELF (Executable and Linkable Format) ด้วยตัวเอง โดยบอกว่านี่ช่วยให้เข้าใจส่วนพื้นฐานของไฟล์ปฏิบัติการได้มาก อีกทั้งบทความนี้ยังมีประโยชน์สำหรับคนที่ต้องการแนวทางแบบมองจากบนลงล่าง แทนที่จะเป็นวิธีแบบดั้งเดิมที่ไล่จากล่างขึ้นบน

  • ผู้ใช้อีกคนอธิบายว่าแม้อาจคิดว่าโปรแกรมเริ่มทำงานที่ main แต่ในความเป็นจริงมันเริ่มที่ _start โดย _start จะทำงานสำคัญหลายอย่างรวมถึงการเรียก main และนี่ไม่ใช่สิ่งที่เฉพาะกับภาษา C แต่เป็นจุดเริ่มต้นของไบนารีที่ไม่ขึ้นกับภาษา

  • ผู้ใช้คนหนึ่งกล่าวว่าบทความของ Julia ยอดเยี่ยมเสมอ และบอกว่าตนได้ผลลัพธ์ที่ดีในการสอนผู้คนว่าโค้ดที่คอมไพล์แล้วไม่ได้ซ่อนความลับไว้ ด้วยการสาธิตคำสั่ง strings

  • ผู้ใช้คนหนึ่งเล่าว่าตนเริ่มศึกษาหัวข้อนี้ครั้งแรกตอนเปลี่ยนเส้นทางอาชีพทางวิชาการจากคณิตศาสตร์ไปสู่วิทยาการคอมพิวเตอร์ และไม่เคยเสียใจกับการลงลึกเช่นนี้ อีกทั้ง Julia เองก็มีพื้นฐานด้านคณิตศาสตร์ด้วย และเขาคิดว่าความต้องการในการให้เหตุผลแบบมองจากบนลงล่างนี้อาจเป็นสิ่งที่พานักคณิตศาสตร์ไปสู่การทดลองลักษณะนี้

  • ผู้ใช้คนหนึ่งสะท้อนว่าไฟล์ปฏิบัติการนั้นผูกกับแพลตฟอร์ม และแบ่งปันประสบการณ์ตอนที่พิสูจน์ได้ว่า “ไฟล์ปฏิบัติการที่พกพาได้จริง” สามารถรันได้บนหลายแพลตฟอร์ม ซึ่งหมายความว่าคำตอบของปัญหาข้ามแพลตฟอร์มที่เราเคยพยายามแก้ด้วยวิธีต่าง ๆ เช่น Java และไลบรารีข้ามแพลตฟอร์มนั้น อยู่ตรงหน้ามานานแล้ว

  • ผู้ใช้คนหนึ่งเล่าว่าช่วงต้นทศวรรษ 90 เขาหลงใหลในฟอร์แมตของไฟล์ปฏิบัติการมากจนเขียนโปรแกรมดูไฟล์ปฏิบัติการของ DOS และ Windows ด้วย Modula 2 โปรแกรมนี้ออกเป็นแชร์แวร์ในปี 1991 ภายใต้ชื่อ VEXE ได้รับความนิยมระดับหนึ่งในหมู่แคร็กเกอร์ และยังถูกกล่าวถึงในบทเรียนของ +ORC ด้วย

  • ผู้ใช้คนหนึ่งบอกว่าการพิมพ์ไฟล์ไบนารีออกสู่เทอร์มินัลเป็นต้นเหตุแห่งความเศร้า และตัวเขาเองชอบใช้ hexdump -C มากกว่า

  • ผู้ใช้หลายคนกล่าวว่านี่เป็นเธรดที่ยอดเยี่ยมเกี่ยวกับหัวข้อนี้

  • ผู้ใช้คนหนึ่งแนะนำให้ผู้ที่สนใจหัวข้อนี้ลองอ่าน Cosmopolitan และ RedBean รวมถึง "αcτµαlly pδrταblε εxεcµταblε (2020)"