diff --git a/src/link.rs b/src/link.rs
index 8fc98075732a14f5f4e2382499e17ec52cb02b76..4b433031a31a53d15fac3e360fa6781ac19e345b 100644
--- a/src/link.rs
+++ b/src/link.rs
@@ -12,17 +12,20 @@
 //! generates a binary that includes Pip MPU and the user code as root
 //! partition
 
-
-use anyhow::Result;
+use anyhow::{anyhow, Result};
 use clap::Parser;
 use elf::endian::AnyEndian;
 use std::path::PathBuf;
 
-use pip_mpu_relocate::reloc::RelIter;
-use pip_mpu_relocate::relocate::relocate;
-use pip_mpu_relocate::symbols::SymbolsQuery;
+// use pip_mpu_relocate::reloc::RelIter;
+// use pip_mpu_relocate::relocate::relocate;
+// use pip_mpu_relocate::symbols::SymbolsQuery;
 use std::io::Write;
 
+const PADDING_SIZE: usize = 32;
+const PADDING_BUFFER: [u8; PADDING_SIZE] = [0xff; PADDING_SIZE];
+const PIP_EXPORT_SECTIONS: &'static [&str] = &[".vector_table", ".text", ".data"];
+
 /// Options for the link subcommand
 #[derive(Parser, Debug)]
 pub struct Opts {
@@ -37,29 +40,56 @@ pub struct Opts {
 
     /// Path the Pipcore MPU elf file
     #[arg(long, short)]
-    pip_elf: Option<PathBuf>
-        
+    pip_elf: Option<PathBuf>,
 }
 
-pub fn link(opts: Opts) -> Result<()> {
+/// Dump the binary content of the given sections to the output file.
+///
+/// It returns the number of bytes writen
+fn dump_sections<'s, T: Write>(
+    elf: &elf::ElfBytes<AnyEndian>,
+    section_names: &[&str],
+    output: &mut T,
+) -> Result<usize> {
+    let mut output_size = 0;
+
+    for section_name in section_names {
+        let section = match elf.section_header_by_name(section_name)? {
+            None => return Err(anyhow!("Section {section_name} not found")),
+            Some(s) => s,
+        };
+        let (bytes, compression) = elf.section_data(&section)?;
+        assert_eq!(compression, None);
+        output.write_all(bytes)?;
+        output_size += bytes.len();
+    }
+    Ok(output_size)
+}
 
+fn align(value: usize, align: usize) -> usize {
+    let a = value & (align - 1);
+    if a == 0 {
+        0
+    } else {
+        align - a
+    }
+}
+
+pub fn link(opts: Opts) -> Result<()> {
     // First, open and parse both crt0 and user_code elf files
-    
+
     let crt0_elf_file = std::fs::read(&opts.crt0_elf)?;
     let crt0_elf_data = crt0_elf_file.as_slice();
-    let crt0_elf = elf::ElfBytes::<AnyEndian>::minimal_parse(crt0_elf_data)?;
+    let _crt0_elf = elf::ElfBytes::<AnyEndian>::minimal_parse(crt0_elf_data)?;
 
     let user_code_elf_file = std::fs::read(&opts.user_code_elf)?;
     let user_code_elf_data = user_code_elf_file.as_slice();
-    let user_code_elf = elf::ElfBytes::<AnyEndian>::minimal_parse(user_code_elf_data)?;
-
+    let _user_code_elf = elf::ElfBytes::<AnyEndian>::minimal_parse(user_code_elf_data)?;
 
     // Then open Pip elf file if necessary
     let pip_elf_data = match opts.pip_elf {
         None => None,
-        Some(pip_path) => {
-            Some(std::fs::read(&pip_path)?)
-        }
+        Some(pip_path) => Some(std::fs::read(&pip_path)?),
     };
 
     let pip_elf = match pip_elf_data {
@@ -69,7 +99,41 @@ pub fn link(opts: Opts) -> Result<()> {
     // When reaching here, all files were opened and parsed
     // we can safely open the output file
     let mut output = std::fs::File::create(opts.output)?;
-    writeln!(output, "Yeah it works")?;
-    
+
+    // First, if needed, output pip binary, padded to 32 bytes
+    if let Some(pip_elf) = pip_elf {
+        let output_size = dump_sections(&pip_elf, PIP_EXPORT_SECTIONS, &mut output)?;
+        // If ouput size is not align on configured padding size bytes, add some padding
+        let pad_bytes = align(output_size, PADDING_SIZE);
+        if pad_bytes > 0 {
+            output.write_all(&PADDING_BUFFER[0..pad_bytes])?;
+        }
+    }
     Ok(())
 }
+
+#[cfg(test)]
+mod tests {
+    use super::align;
+
+    #[test]
+    fn test_align() {
+        assert_eq!(align(0, 8), 0);
+        assert_eq!(align(1, 8), 7);
+        assert_eq!(align(2, 8), 6);
+        assert_eq!(align(3, 8), 5);
+        assert_eq!(align(4, 8), 4);
+        assert_eq!(align(5, 8), 3);
+        assert_eq!(align(6, 8), 2);
+        assert_eq!(align(7, 8), 1);
+
+        assert_eq!(align(8, 8), 0);
+        assert_eq!(align(9, 8), 7);
+        assert_eq!(align(10, 8), 6);
+        assert_eq!(align(11, 8), 5);
+        assert_eq!(align(12, 8), 4);
+        assert_eq!(align(13, 8), 3);
+        assert_eq!(align(14, 8), 2);
+        assert_eq!(align(15, 8), 1);
+    }
+}