უკან დაბრუნება
პროტოტიპი: შესრულებადი ფაილი SQLite მონაცემთა ბაზად გადაიქცევა
SiTech AI Team2 წთ. საკითხავი

პროტოტიპი: შესრულებადი ფაილი SQLite მონაცემთა ბაზად გადაიქცევა

დეველოპერმა ფარიდ ზაქარიამ შექმნა SELF — ექსპერიმენტული ფორმატი, რომელიც პროგრამას და მის ბიბლიოთეკებს ერთ SQLite ბაზაში ინახავს და readelf-სა თუ ldd-ს SQL მოთხოვნებით ცვლის.

დეველოპერმა ფარიდ ზაქარიამ პროტოტიპი გამოაქვეყნა, რომელიც ბინარული ფაილების ELF ფორმატს SQLite-ით ცვლის. პროექტს SELF (Structured Executable & Linkable Format) ჰქვია: მისი შედეგი ჩვეულებრივი SQLite ფაილია, რომელსაც შესრულების უფლება ენიჭება და რომელიც მუშაობს, ხოლო binutils-ის ინსტრუმენტების ნაცვლად SQL მოთხოვნები გამოიყენება. კოდი GitHub-ზე, selfdb რეპოზიტორიაშია.

ELF უკვე მონაცემთა ბაზაა

ზაქარიას არგუმენტია, რომ ELF თავისთავად მონაცემთა ბაზაა — უბრალოდ ხელით განხორციელებული: სტრიქონების ცხრილები სტრიქონების ინტერნირებაა, .gnu.hash ხელით აწყობილი ინდექსია, სექციების სათაურების ცხრილი ცხრილების ცხრილია, ხოლო სტრიქონების ცხრილში ოფსეტები გარე გასაღების როლს თამაშობს. ფორმატი მჭიდროა, თვითაღწერადი სქემა არ აქვს და ყველა ინსტრუმენტი, რომელიც მას კითხულობს, ერთსა და იმავე პარსერს თავიდან წერს. მისი ადრინდელი ხელსაწყო sqlelf ELF ფაილებს SQL ვირტუალურ ცხრილებად წარმოადგენდა, რათა დეველოპერებს readelf-ისა და grep-ის კომბინაციის ნაცვლად SELECT მოთხოვნები დაეწერათ.

რას შეიცავს SELF ფაილი

შესრულებისთვის ორი ცხრილი საკმარისია: self_meta ELF-ის სათაურს წყვილებად ინახავს, ხოლო segments თითო პროგრამულ სათაურზე ერთ სტრიქონს ინახავს სეგმენტის ბაიტებით BLOB სვეტში. ერთი symbols ცხრილი ერთი b-tree ინდექსით ცვლის ELF-ის რამდენიმე სექციას და ხელით აწყობილ .gnu.hash სტრუქტურას, სიმბოლოების ვერსიები კი ჩვეულებრივი სვეტია. sections, notes და dynamic_entries ცხრილები მხოლოდ ინსტრუმენტებისთვის არსებობს: მათი წაშლის შემდეგ პროგრამა მაინც მუშაობს, რაც იმას ნიშნავს, რომ strip არის DELETE და VACUUM, patchelf — UPDATE, ხოლო ldd — JOIN-ის ხედი.

როგორ უშვებს მას ბირთვი

SQLite თავისი სათაურის 68-ე ბაიტზე ოთხბაიტიან application_id ველს იტოვებს; SELF მასში ასოებს SELF ჩაწერს, ამიტომ ჩვეულებრივი ბაზა არასოდეს ემთხვევა. Linux-ის binfmt_misc-ის რეგისტრაცია ბირთვს ავალებს, რომ ფაილი პატარა ინტერპრეტატორს, self-exec-ს გადასცეს, რომელიც ჩასატვირთ სეგმენტებს მეხსიერებაში ათავსებს, გადაადგილებას ასრულებს და შესვლის წერტილზე გადადის. თავად ინტერპრეტატორი ELF უნდა დარჩეს, რადგან ის, რომელიც ამ მაგიურ ბაიტებსაც დაემთხვეოდა, რეკურსიაში გადავარდებოდა და ბირთვი ELOOP-ს დააბრუნებდა.

ღირებულება და მთელი userland ერთ ფაილში

დინამიკური ბმა ორი გზით გამოიცადა: ჯერ ld.so დარჩა და ბიბლიოთეკების ძებნა glibc-ის rtld-audit ინტერფეისით SQL-ის მეშვეობით სრულდებოდა, შემდეგ კი შეიქმნა პროტოტიპი ლინკერი, რომელიც მთელ ბმას SQL-ში ასრულებს. მოცულობით SELF ფაილი ეკვივალენტურ ELF-ზე დაახლოებით ორჯერ დიდია, თუმცა მისი დიდი ნაწილი არასავალდებულო, დამხმარე მონაცემებია: გასუფთავების შემდეგ coreutils-ის ბინარი 1 794 048 ბაიტი იყო ELF-ის 1 768 632-ის წინააღმდეგ — ერთ პროცენტში. გაშვებას ფიქსირებული ~5 მწმ ემატება, პლუს გადაწერა, რომელიც გამოსახულების ზომის პროპორციულია; ვინაიდან ბაიტები b-tree-დან კოპირდება და არა იმეხსიერება, ერთი პროგრამის ორი პროცესი ტექსტის გვერდებს არ იზიარებს.

მთელი userland-ის ერთ ბაზაში ჩაწერამ ყველაზე შთამბეჭდავი შედეგი მისცა: 723 შესრულებადი ფაილი, რომლებიც 400 სხვადასხვა ბიბლიოთეკას იყენებს, გადაიქცა 1123 ობიექტად და 346 386 სიმბოლოდ ერთ 611,9 მიბაიტიან ფაილში — უფრო პატარაში, ვიდრე ის 644,4 მიბაიტი ELF ფაილები, საიდანაც შეიქმნა. LD_PRELOAD ცხრილის სტრიქონი ხდება, ამიტომ მისი ჩართვა-გამორთვა ტრანზაქციაა.

SSiTech

SiTech — AI-გაძლიერებული ვებ დეველოპმენტი

ვქმნით სწრაფ, თანამედროვე ვებსაიტებს და AI-ს ვაერთიანებთ ქართული ბიზნესებისთვის. გაქვთ პროექტი ან კითხვა? სიამოვნებით დაგეხმარებით.